• [poj3321]Apple Tree_dfs序_树状数组


    Apple Tree poj-3321

        题目大意:给你一个根固定的树,每一个点的点权是0或1,查询子树点权和。

        注释:$1le n le 10^5$。

          想法:刚刚学习dfs序,刷到水题偶哈哈。

            什么是dfs序?就是在遍历树的时候记录的每个点的出栈入栈序。这样就可以保证每一个节会出现两次且它的子树被其夹在中间。

          然后,子树信息就可以通过维护序列的鬼东西维护了qwq。

          紧接着,我们用树状数组维护被节点夹着的区间,就是端点节点的子树,用树状数组更新即可。

        最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxn 100010
    using namespace std;
    int tot,cnt;
    int to[2*maxn],head[maxn],nxt[2*maxn];
    int d[2*maxn];
    int p1[maxn],p2[maxn];
    int tree[4*maxn];
    inline void add(int x,int y)
    {
    	to[++tot]=y;
    	nxt[tot]=head[x];
    	head[x]=tot;
    }
    int lowbit(int x)
    {
    	return x&(-x);
    }
    void dfs(int pos,int fa)//初始构造dfs序
    {
    	d[++cnt]=1;
    	p1[pos]=cnt;
    	for(int i=head[pos];i;i=nxt[i])
    	{
    		if(to[i]==fa) continue;
    		dfs(to[i],pos);
    	}
    	p2[pos]=cnt;
    }
    void fix(int x,int ch)
    {
    	for(int i=x;i<=cnt;i+=lowbit(i))
    	{
    		tree[i]+=ch;
    	}
    }
    int query(int x)
    {
    	int ans=0;
    	for(int i=x;i;i-=lowbit(i))
    	{
    		ans+=tree[i];
    	}
    	return ans;
    }
    void original()
    {
    	cnt=tot=0;
    	memset(tree,0,sizeof tree);
    	memset(head,0,sizeof head);
    }
    int main()
    {
    	int n,m;
    	while(~scanf("%d",&n))
    	{
    		original();
    		for(int a,b,i=1;i<n;i++)
    		{
    			scanf("%d%d",&a,&b);
    			add(a,b);
    			add(b,a);
    		}
    		dfs(1,0);
    		for(int i=1;i<=n;i++)//别忘了建树
    		{
    			fix(p1[i],1);
    		}
    		// for(int i=1;i<=cnt;i++)
    		// {
    		// 	printf("%d ",query(i));
    		// }
    		// puts("");
    		char s[20];
    		scanf("%d",&m);
    		for(int x,i=1;i<=m;i++)
    		{
    			scanf("%s",s+1);
    			if(s[1]=='C')
    			{
    				scanf("%d",&x);
    				if(d[p1[x]]==1) fix(p1[x],-1);
    				else fix(p1[x],1);
    				d[p1[x]]^=1;
    			}
    			else
    			{
    				scanf("%d",&x);
    				printf("%d
    ",query(p2[x])-query(p1[x]-1));
    			}
    		}
    	}
    	return 0;
    }
    // int main()
    // {
    // 	int n;
    // 	scanf("%d",&n);
    // 	for(int a,b,i=1;i<n;i++)
    // 	{
    // 		scanf("%d%d",&a,&b);
    // 		add(a,b);
    // 		add(b,a);
    // 	}
    // 	dfs(1,0);
    // 	for(int i=1;i<=cnt;i++)
    // 	{
    // 		printf("%d ",d[i]);
    // 	}
    // 	puts("");
    // 	for(int i=1;i<=n;i++)
    // 	{
    // 		printf("%d %d
    ",p1[i],p2[i]);
    // 	}
    // 	return 0;
    // }
    

         小结:dfs序好东西好东西... ...

  • 相关阅读:
    生成随机数的范围的公式
    正则匹配<img src="xxxxxx" alt="" />标签的相关写法
    js 日常问题记录
    css 三角实例
    /users/products.:format 这种写法的其对应解析字符写法
    package.json 的语法解释
    replace 全局替换 和 数组去空
    js checkbox获取选中的值
    JavaScript基础知识一
    移动 Web 设计
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8710605.html
Copyright © 2020-2023  润新知