zoukankan      html  css  js  c++  java
  • luogu P6018 [Ynoi2010]Fusion tree

    之前膜你赛好像考过好几次这种类型的题目,但我太菜了一直没听懂。

    有个很常见的trick是统一维护一个点所有儿子的异或和,单独维护父亲。然后再上能维护全局+1的01trie这题就做完了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    
    using namespace std;
    
    const int N=500009;
    int n,m,head[N],cnt,rt[N],p[N],F[N],addv[N];
    struct Edge
    {
    	int nxt,to;
    }g[N*2];
    struct Trie
    {
    	#define MaxN 25
    	int w[2*MaxN*N],ch[2*MaxN*N][2],xorv[2*MaxN*N],pool;
    	
    	void push_up(int k)
    	{
    		w[k]=xorv[k]=0;
    		if(ch[k][0])
    			w[k]^=w[ch[k][0]],
    			xorv[k]^=xorv[ch[k][0]]<<1;
    		if(ch[k][1])
    			w[k]^=w[ch[k][1]],
    			xorv[k]^=(xorv[ch[k][1]]<<1)|w[ch[k][1]];
    	}
    	
    	void Insert(int &k,int x,int dep)
    	{
    		if(!k) k=++pool;
    		if(dep==MaxN) { w[k]^=1;return; }
    		Insert(ch[k][x&1],x>>1,dep+1);
    		push_up(k);
    	}
    	
    	void addall(int k)
    	{
    		swap(ch[k][0],ch[k][1]);
    		if(ch[k][0]) addall(ch[k][0]);
    		push_up(k);
    	}
    }T;
    
    void add(int from,int to)
    {
    	g[++cnt].nxt=head[from];
    	g[cnt].to=to;
    	head[from]=cnt;
    }
    
    int read()
    {
    	int x=0;
    	char c=getchar();
    	while(c<'0'||c>'9')
    		c=getchar();
    	while(c>='0'&&c<='9')
    		x=x*10+c-'0',c=getchar();
    	return x;
    }
    
    void init()
    {
    	n=read(),m=read();
    	for (int x,y,i=1;i<n;i++)
    		x=read(),y=read(),
    		add(x,y),add(y,x);
    	for (int i=1;i<=n;i++)
    		p[i]=read();
    }
    
    void dfs(int x,int fa)
    {
    	for (int i=head[x];i;i=g[i].nxt)
    	{
    		int v=g[i].to;
    		if(v==fa)
    			continue;
    		F[v]=x;
    		dfs(v,x);
    		T.Insert(rt[x],p[v],0);
    	}
    }
    
    void work()
    {
    	dfs(1,-1);
    	int opt,x,v;
    	while(m--)
    	{
    		opt=read();
    		if(opt==3)
    		{
    			x=read();
    			int ans=T.xorv[rt[x]];
    			if(x!=1)
    			{
    				int y=F[x];
    				if(y!=1)
    					ans^=p[y]+addv[F[y]];
    				else
    					ans^=p[y];
    			}
    			printf("%d
    ",ans);
    		}
    		else if(opt==2)
    		{
    			x=read(),v=read();
    			if(x!=1)
    				T.Insert(rt[F[x]],p[x]+addv[F[x]],0),
    				T.Insert(rt[F[x]],p[x]-v+addv[F[x]],0);
    			p[x]-=v;
    		}
    		else
    		{
    			x=read(),T.addall(rt[x]),addv[x]++;
    			if(x!=1)
    			{
    				int y=F[x];
    				if(y!=1)
    					T.Insert(rt[F[y]],p[y]+addv[F[y]],0),
    					T.Insert(rt[F[y]],p[y]+1+addv[F[y]],0);
    				p[y]++;
    			}
    		}
    	}
    }
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    vue+elementUI实现权限的部门管理
    vue+elementUI实现权限的部门管理
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    20 种最奇怪的编程语言
    WinForm导出文件
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13301758.html
Copyright © 2011-2022 走看看