bzoj 4811: [Ynoi2017]由乃的OJ
Posted ccz181078
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4811: [Ynoi2017]由乃的OJ相关的知识,希望对你有一定的参考价值。
树链剖分,用zkw线段树维护每条链两个方向上对每一位的变换情况,由于位数较少,可以用两个unsigned long long表示
#include<cstdio> typedef unsigned long long u64; const int N=100007; char buf[N*100],*ptr=buf-1; int _(){ int x=0,c=*++ptr; while(c<48)c=*++ptr; while(c>47)x=x*10+c-48,c=*++ptr; return x; } u64 _u64(){ u64 x=0; int c=*++ptr; while(c<48)c=*++ptr; while(c>47)x=x*10+c-48,c=*++ptr; return x; } int es[N*2],enx[N*2],e0[N],ep=2,tp[N]; u64 v[N]; int fa[N],sz[N],top[N],dep[N],son[N],id[N],idp=0,idr[N]; int n,m,k; u64 vs[262777][4]; void f1(int w,int pa){ dep[w]=dep[fa[w]=pa]+1; sz[w]=1; for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=pa){ f1(u,w); sz[w]+=sz[u]; if(sz[u]>sz[son[w]])son[w]=u; } } } void f2(int w,int tp){ top[w]=tp; id[w]=++idp; idr[idp]=w; if(son[w])f2(son[w],tp); for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=fa[w]&&u!=son[w])f2(u,u); } } int s1[107],p1,s2[107],p2,s3[10007],s4[10007],p3,p4; void find(int l,int r,int tp){ p1=p2=0; for(l+=131071,r+=131073;r-l!=1;l>>=1,r>>=1){ if(~l&1)s1[p1++]=l^1; if(r&1)s2[p2++]=r^1; } if(!tp){ for(int i=0;i<p2;++i)s4[p4++]=s2[i]; while(p1)s4[p4++]=s1[--p1]; }else{ for(int i=0;i<p2;++i)s3[p3++]=s2[i]; while(p1)s3[p3++]=s1[--p1]; } } #define cal(a,b,c0,c1) (a)=((~(b)&(c0))|((b)&(c1))) void init(int w,int tp,u64 v){ u64*a=vs[w]; if(tp==1){ a[0]=a[2]=0ll&v; a[1]=a[3]=-1ll&v; }else if(tp==2){ a[0]=a[2]=0ll|v; a[1]=a[3]=-1ll|v; }else if(tp==3){ a[0]=a[2]=0ll^v; a[1]=a[3]=-1ll^v; } } void up(u64*a,u64*l,u64*r){ cal(a[0],l[0],r[0],r[1]); cal(a[1],l[1],r[0],r[1]); cal(a[2],r[2],l[2],l[3]); cal(a[3],r[3],l[2],l[3]); } u64 _v0,_v1; void get(int x,int y){ p3=p4=0; int a=top[x],b=top[y]; while(a!=b){ if(dep[a]>dep[b]){ find(id[a],id[x],0); x=fa[a],a=top[x]; }else{ find(id[b],id[y],1); y=fa[b],b=top[y]; } } if(dep[x]>dep[y]){ find(id[y],id[x],0); }else{ find(id[x],id[y],1); } u64 v0=0ll,v1=-1ll; for(int i=0;i<p4;++i){ u64*a=vs[s4[i]]; cal(v0,v0,a[2],a[3]); cal(v1,v1,a[2],a[3]); } while(p3){ u64*a=vs[s3[--p3]]; cal(v0,v0,a[0],a[1]); cal(v1,v1,a[0],a[1]); } _v0=v0,_v1=v1; } int main(){ fread(buf,1,sizeof(buf),stdin)[buf]=0; n=_();m=_();k=_(); for(int i=1;i<=n;++i){ tp[i]=_(); v[i]=_u64(); } for(int i=1,a,b;i<n;++i){ a=_();b=_(); es[ep]=b;enx[ep]=e0[a];e0[a]=ep++; es[ep]=a;enx[ep]=e0[b];e0[b]=ep++; } f1(1,0);f2(1,1); for(int i=1;i<=n;++i)init(id[i]+131072,tp[i],v[i]); for(int i=131071;i;--i)up(vs[i],vs[i<<1],vs[i<<1|1]); for(int i=0;i<m;++i){ int o=_(),x=_(),y=_(); u64 z=_u64(); if(o==1){ get(x,y); u64 r=0,r0,r1; for(int i=63;i>=0;--i)if((r|1llu<<i)<=z){ cal(r0,r,_v0,_v1); cal(r1,(r|1llu<<i),_v0,_v1); if(r0<r1)r|=1llu<<i; } cal(r0,r,_v0,_v1); printf("%llu\n",r0); }else{ init(id[x]+131072,tp[x]=y,v[x]=z); for(int w=id[x]+131072>>1;w!=1;w>>=1)up(vs[w],vs[w<<1],vs[w<<1^1]); } } return 0; }
以上是关于bzoj 4811: [Ynoi2017]由乃的OJ的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ4811 [Ynoi2017]由乃的OJ 树链剖分 位运算
bzoj4811[Ynoi2017]由乃的OJ 树链剖分+线段树区间合并