zoukankan      html  css  js  c++  java
  • CodeForces 877E DFS序+线段树

    CodeForces 877E DFS序+线段树

    题意

    就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身一共有几个灯是亮的。pow x,表示你需要改变x的子树和x本身上的灯的状态。

    题解思路

    这个题肯定是用DFS序了,为啥?因为树不好操作啊(我也不会啊),使用DFS序可以把树压成一维的一串数,这样就可以使用线段树来进行区间操作了。

    话说这个题是我暑假限时训练中做的,看到这个题老开心了,但是让我万万没想到的是,这个题我交了11次才过,太心酸了。

    代码实现

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<iostream>
    #include<vector>
    using namespace std;
    const int  maxn=2e5+100;
    struct node{
    	int l, r;
    	int sum;
    	int lazy;
    }t[maxn<<2];
    vector<int> g[maxn];
    int num[maxn];
    int in[maxn], out[maxn], rk[maxn], cnt;
    int n, m;
    void dfs(int u, int fa) //
    {
    	in[u]=++cnt;//这个是u进去的是时间
    	rk[cnt]=u; //不要忘了这个,这个是新生成的序列,也就是树被压成一维的那个数列。就是这忘了,害的我好苦。
    	int len=g[u].size();
    	for(int i=0; i<len; i++)
    	{
    		int v=g[u][i];
    		if(v==fa) continue;
    		dfs(v, u);	
    	}	
    	out[u]=cnt;
    }
    void up(int rt)
    {
    	t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum;
    }
    void build(int rt, int l, int r)
    {
    	t[rt].l=l;
    	t[rt].r=r;
    	t[rt].sum=0;
    	t[rt].lazy=0;
    	if(l==r)
    	{
    		t[rt].sum=num[rk[l]]; //这里也不要能错了,很重要。
    		return ;
    	}
    	int  mid=(l+r)>>1;
    	build(rt<<1, l, mid);
    	build(rt<<1|1, mid+1, r);
    	up(rt);
    }
    void down(int rt)
    {
    	if(t[rt].lazy==0) return ;
    	int ls=rt<<1, rs=rt<<1|1;
    	t[ls].lazy=!t[ls].lazy;
    	t[ls].sum=t[ls].r-t[ls].l+1-t[ls].sum;
    	
    	t[rs].lazy=!t[rs].lazy;
    	t[rs].sum=t[rs].r-t[rs].l+1-t[rs].sum;
    	
    	t[rt].lazy=0;
    }
    void update(int rt, int l, int r)
    {
    	if(l <= t[rt].l && t[rt].r <= r )
    	{
    		t[rt].lazy = !t[rt].lazy;
    		t[rt].sum=t[rt].r-t[rt].l+1-t[rt].sum;
    		return ;
    	}
    	down(rt);
    	int mid=(t[rt].l+t[rt].r)>>1;
    	if(l<=mid) update(rt<<1, l, r);
    	if(r>mid)  update(rt<<1|1, l, r);
    	up(rt);
    }
    int query(int rt, int l, int r)
    {
    	if(l <= t[rt].l && t[rt].r <= r)
    	{
    		return t[rt].sum;
    	}
    	int ans=0;
    	down(rt);
    	int mid=(t[rt].l+t[rt].r)>>1;
    	if(l<=mid) ans+=query(rt<<1, l, r);
    	if(r>mid) ans+=query(rt<<1|1, l, r);
    	return ans;
    }
    void init()
    {
    	cnt=0;
    	for(int i=0; i<=n; i++)
    	{
    		g[i].clear();
    	}
    }
    int main()
    {
    	scanf("%d", &n);
    	{
    		cnt=0;
    		int x;
    		string op;
    		if(n==1)
    		{
    			scanf("%d", &x);
    			scanf("%d" , &m);
    			while(m--)
    			{
    				int tmp;
    				cin>>op;
    				scanf("%d", &tmp);
    				if(op=="get") printf("%d
    ", x);
    				else x=!x;
    			}
    			return 0;
    		}
    		for(int i=2; i<=n; i++)
    		{
    			scanf("%d", &x);
    			g[x].push_back(i);
    			g[i].push_back(x);
    		}
    		dfs(1, 0);
    		for(int i=1; i<=n; i++)
    		{
    			scanf("%d", &num[i]);
    		}
    		build(1, 1, n);
    		scanf("%d", &m);
    		for(int i=1; i<=m; i++)
    		{
    			cin>>op;
    			scanf("%d", &x);
    			if(op=="get")
    			{
    				printf("%d
    ", query(1, in[x], out[x]));
    			}
    			else
    			{
    				update(1, in[x], out[x]);
    			}
    		}
    	}
    	return 0;
    }
    
    欢迎评论交流!
  • 相关阅读:
    Enterprise Library 企业库 V4.1
    跨域实现IFRAME自适应高度
    微软企业库4.1学习笔记(二)各功能之间的依赖关系以及对象创建
    微软企业库4.1学习笔记(三)企业库迁移和并行使用,以及企业库的扩展
    微软企业库4.1学习笔记(五)对象创建和依赖注入方法
    判断 iframe 是否加载完成的完美方法
    对JavaScript调用堆栈和setTimeout用法的深入研究
    工作流技术杂谈
    企业流程管理平台V2.0介绍(.NET平台下的工作流)
    c#操作oracle lob字段[转自 芽芽的回收站]
  • 原文地址:https://www.cnblogs.com/alking1001/p/11405929.html
Copyright © 2011-2022 走看看