一本通1762:与非

链接

对于不满足结合律的运算,要处理出两个方向的结果,查询时也要注意方向。

(太菜了。。。被卡常惹。。。

#include<bits/stdc++.h>
#define re register
#define IL inline
#define LL unsigned int
using namespace std;
const int N=1e5+3;
struct hh{
	int to,nxt;
}e[N<<1];
int n,m,k,K,num,fir[N],dfn[N],rev[N],top[N],siz[N],son[N],dep[N],fa[N];
LL w[N],Ans,ans[32];
IL LL in(){
	char c;
	while((c=getchar())<'0'||c>'9');
	LL x=c-'0';
	while((c=getchar())>='0'&&c<='9')
	  x=x*10+c-'0';
	return x;
}
IL void add(int x,int y){e[++num]=(hh){y,fir[x]},fir[x]=num;}
IL int nand(int x,int y){return !(x&y);}
void dfs1(int u,int f){
	fa[u]=f,dep[u]=dep[f]+1,siz[u]=1;
	for(re int i=fir[u],v;v=e[i].to;i=e[i].nxt)
	  if(v^f){
	  	dfs1(v,u),siz[u]+=siz[v];
	  	if(siz[son[u]]<siz[v]) son[u]=v;
		}
}
void dfs2(int u,int t){
	top[u]=t,rev[dfn[u]=++num]=u;
	if(son[u]) dfs2(son[u],t);
	for(re int i=fir[u],v;v=e[i].to;i=e[i].nxt)
	  if(v^fa[u]&&v^son[u]) dfs2(v,v);
}
IL int get_lca(int x,int y){
	while(top[x]^top[y]) dep[top[x]]<dep[top[y]]?y=fa[top[y]]:x=fa[top[x]];
	return dep[x]<dep[y]?x:y;
}
struct segment{
	int L[32][N<<2][2],R[32][N<<2][2];
	IL void pushup(int k){
		int ls=k<<1,rs=k<<1|1;
		for(re int i=0;i<K;++i)
		  L[i][k][0]=L[i][rs][L[i][ls][0]],
		  L[i][k][1]=L[i][rs][L[i][ls][1]],
		  R[i][k][0]=R[i][ls][R[i][rs][0]],
		  R[i][k][1]=R[i][ls][R[i][rs][1]];
	}
	IL void gx(int k,LL w){
		for(re int i=0;i<K;++i)
		  L[i][k][0]=R[i][k][0]=nand(0,w>>i&1),
		  L[i][k][1]=R[i][k][1]=nand(1,w>>i&1);
	}
	void build(int k,int l,int r){
		if(l==r){gx(k,w[rev[l]]);return;}
		int mid=l+r>>1;
		build(k<<1,l,mid),build(k<<1|1,mid+1,r),pushup(k);
	}
	void mdy(int k,int l,int r,int u,LL v){
		if(l==r){gx(k,v);return;}
		int mid=l+r>>1;
		if(u<=mid) mdy(k<<1,l,mid,u,v);
		else mdy(k<<1|1,mid+1,r,u,v);
		pushup(k);
	}
	void query_R(int k,int l,int r,int ll,int rr){//从下到上 
		if(l>=ll&&r<=rr){
			for(re int i=0;i<K;++i)
		    ans[i]=R[i][k][ans[i]];
		  return;
		}
		int mid=l+r>>1;
		if(rr>mid) query_R(k<<1|1,mid+1,r,ll,rr);
		if(ll<=mid) query_R(k<<1,l,mid,ll,rr);
	}
	void query_L(int k,int l,int r,int ll,int rr){//从上到下 
		if(l>=ll&&r<=rr){
			for(int i=0;i<K;++i)
		    ans[i]=L[i][k][ans[i]];
		  return;
		}
		int mid=l+r>>1;
		if(ll<=mid) query_L(k<<1,l,mid,ll,rr);
		if(rr>mid) query_L(k<<1|1,mid+1,r,ll,rr);
	}
}T;
void dfs(int y,int lca){
	if(top[y]==top[lca]){
		if(y^lca) T.query_L(1,1,n,dfn[lca]+1,dfn[y]);
		return;
	}
	dfs(fa[top[y]],lca);
	T.query_L(1,1,n,dfn[top[y]],dfn[y]);
}
int Query(int x,int y){
	memset(ans,Ans=0,sizeof(ans));
	int lca=get_lca(x,y);
	while(top[x]^top[lca]) 
	  T.query_R(1,1,n,dfn[top[x]],dfn[x]),x=fa[top[x]];
	T.query_R(1,1,n,dfn[lca],dfn[x]);
	dfs(y,lca);
	for(int i=0;i<K;++i) Ans|=ans[i]<<i;
	return Ans;
}
int main()
{
	LL x,y,z;char s[10];
	n=in(),m=in(),k=K=in();
	for(re int i=1;i<=n;++i) w[i]=in();
	for(re int i=1;i<n;++i)
	  x=in(),y=in(),
	  add(x,y),add(y,x);
	num=0,dfs1(1,0),dfs2(1,1);
	T.build(1,1,n);
	while(m--){
		scanf("%s",s+1),x=in(),y=in();
		if(s[1]=='Q') printf("%u\n",Query(x,y));
		else T.mdy(1,1,n,dfn[x],y);
	}
	return 0;
}
posted @ 2020-11-03 19:34  (o-ωq)).oO  阅读(230)  评论(2编辑  收藏  举报