1. 程式人生 > >BZOJ 4811: [Ynoi2017]由乃的OJ

BZOJ 4811: [Ynoi2017]由乃的OJ

辣雞csdn要我改密碼所以發晚了

老年選手懶於寫blog(躺

反正也步入晚年,準備AFO

這道題不錯 想寫寫

其實 O ( n k l o g 2

) 的做法並不難想到,我們只要列舉某一位填了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; }