BZOJ 4811: [Ynoi2017]由乃的OJ
阿新 • • 發佈:2018-11-15
辣雞csdn要我改密碼所以發晚了
老年選手懶於寫blog(躺
反正也步入晚年,準備AFO
這道題不錯 想寫寫
其實 的做法並不難想到,我們只要列舉某一位填了0或1結果會是啥就行了
剩下就是樹剖的操作了
然而其實每一位是不必列舉的,線上段樹中,你只要維護全部是0或者全部是1的就可以了
v0[u]=(v0[l]&v1[r])|(~v0[l]&v0[r]);
v1[u]=(v1[l]&v1[r])|(~v1[l]&v0[r]);
因為是沿著路徑走的,所以線段樹也要維護從區間從右往左的這個東西,跟上面道理差不多
.最後每一位貪心取一下,保證一下不超約束就好。
我覺得我有點蛋疼,一開始為了短線段樹打了陣列,後面合併就有點蛋疼了…
後來發現寫結構體的話似乎方便多了、
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long LL;
const int N=1e5+2,inf=1e9+7;
char O[1<<14],*S=O,*T=O;
#define gc (S==T&&(T=(S=O)+fread(O,1,1<<14,stdin),S==T)?-1:*S++)
inline LL read(){
LL x=0,f=1; char ch=gc;
while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=gc;}
while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=gc;}
return x*f;
}
struct E{int y,nex;}e[N<<1];
int len,fir[N],tot,cnt,q,lc[N*3],rc[N*3],n;
LL v0[N*3],v1[N*3],w0[N*3],w1[N*3],a[N],mx;
void ins(int x,int y){
e[++len]=(E){y,fir[x]},fir[x]=len;
}
int id,p[N],dfn[N],sz[N],son[N],dep[N],fa[N],top[N],o[N];
void dfs(int x){
sz[x]=1;
for(int k=fir[x];k;k=e[k].nex){
int y=e[k].y; if(y==fa[x])continue;
fa[y]=x,dep[y]=dep[x]+1,dfs(y); sz[x]+=sz[y];
if(sz[y]>sz[son[x]]) son[x]=y;
}
}
void dfs1(int x,int tp){
dfn[x]=++id,o[id]=x,top[x]=tp;
if(!son[x])return;
dfs1(son[x],tp);
for(int k=fir[x];k;k=e[k].nex)
if(e[k].y!=fa[x] && e[k].y!=son[x]) dfs1(e[k].y,e[k].y);
}
inline LL cal(LL x,int u){
if(p[u]==1) return x&a[u];
if(p[u]==2) return x|a[u];
return x^a[u];
}
void upd(int x,int l,int r){
int u=tot+1;
v0[u]=(v0[l]&v1[r])|(~v0[l]&v0[r]);
v1[u]=(v1[l]&v1[r])|(~v1[l]&v0[r]);
w0[u]=(w0[r]&w1[l])|(~w0[r]&w0[l]);
w1[u]=(w1[r]&w1[l])|(~w1[r]&w0[l]);
v0[x]=v0[u],v1[x]=v1[u],w0[x]=w0[u],w1[x]=w1[u];
}
void bt(int &x,int l,int r){
x=++tot; int mid=l+r>>1;
if(l==r){
int u=o[l];
v0[x]=w0[x]=cal(0,u),v1[x]=w1[x]=cal(mx,u);
return;
}
bt(lc[x],l,mid),bt(rc[x],mid+1,r);
upd(x,lc[x],rc[x]);
}
void cha(int x,int l,int r,int k){
if(l==r){
int u=o[l];
v0[x]=w0[x]=cal(0,u),v1[x]=w1[x]=cal(mx,u);
return;
}
int mid=l+r>>1;
if(k<=mid) cha(lc[x],l,mid,k);
else cha(rc[x],mid+1,r,k);
upd(x,lc[x],rc[x]);
}
int get(int x,int l,int r,int ql,int qr){
if(l==ql && r==qr) return x;
int mid=l+r>>1;
if(ql>mid) return get(rc[x],mid+1,r,ql,qr);
if(qr<=mid) return get(lc[x],l,mid,ql,qr);
int u=++tot;
upd(u,get(lc[x],l,mid,ql,mid),get(rc[x],mid+1,r,mid+1,qr));
return u;
}
int turn(int x){
int u=x; if(u<=cnt) u=tot+2;
v0[u]=v0[x],v1[u]=v1[x],w0[u]=w0[x],w1[u]=w1[x];
swap(v0[u],w0[u]),swap(v1[u],w1[u]);
return u;
}
void solve(int x,int y){
int vx=++tot,vy=++tot;
v0[vx]=v0[vy]=w0[vx]=w0[vy]=0;
v1[vx]=v1[vy]=w1[vx]=w1[vy]=mx;
int fx=top[x],fy=top[y];
while(fx!=fy)
if(dep[fx]>dep[fy]) upd(vx,vx,turn( get(1,1,n,dfn[fx],dfn[x]) )),x=fa[fx],fx=top[x];
else upd(vy,get(1,1,n,dfn[fy],dfn[y]),vy),y=fa[fy],fy=top[y];
if(dep[x]>dep[y]) upd(vx,vx,turn( get(1,1,n,dfn[y],dfn[x]) ));
else upd(vx,vx,get(1,1,n,dfn[x],dfn[y]));
upd(q,vx,vy);
}
int main(){
n=read(); int m=read(),Z=read();
for(int i=1;i<=n;++i) p[i]=read(),a[i]=read();
for(int i=1,x,y;i<n;++i) x=read(),y=read(),ins(x,y),ins(y,x);
dfs(1); dfs1(1,1);
mx=0ull-1; bt(cnt,1,n); cnt=tot;
while(m--){
int u=read(); LL x=read(),y=read(),z=read();
if(u==2) a[x]=z,p[x]=y,cha(1,1,n,dfn[x]);
else{
q=++tot; solve(x,y); LL ans=0,now=0;
for(int i=Z-1;~i;--i)
if(v0[q]&(1ull<<i)) ans+=1ull<<i;
else if(v1[q]&(1ull<<i) && now+(1ull<<i)<=z) now+=1ull<<i,ans+=1ull<<i;
printf("%llu\n",ans);
tot=cnt;
}
}
return 0;
}