1. 程式人生 > >[BZOJ4811][YNOI2017]由乃的OJ(樹鏈剖分+線段樹)

[BZOJ4811][YNOI2017]由乃的OJ(樹鏈剖分+線段樹)

起床困難綜合症那題,只要從高往低貪心,每次暴力跑一邊看這一位輸入0和1分別得到什麼結果即可。

放到序列上且帶修改,只要對每位維護一個線段樹,每個節點分別記錄0和1從左往右和從右往左走完這段區間後變成的數即可。

放到樹上,只要樹鏈剖分即可。但這裡有一個很大的常數k,實際上我們只需要一個數就可以記錄64個二進位制位的資訊,於是複雜度$O(n\log^2 n)$

小錯誤毀一生。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5
#define ls (x<<1) 6 #define rs (ls|1) 7 #define lson ls,L,mid 8 #define rson rs,mid+1,R 9 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 10 #define For(i,x) for (int i=h[x],k; i; i=nxt[i]) 11 typedef unsigned long long ll; 12 using namespace std; 13 14 const int N=100010
; 15 ll z,I=1; 16 int n,m,k,u,v,x,y,op,cnt,tim,pos[N],sz[N],dep[N],son[N],fa[N],dfn[N],top[N]; 17 int h[N],to[N<<1],nxt[N<<1]; 18 struct P{ int op; ll x; }p[N]; 19 struct D{ ll s0,s1; }v1[N<<2],v2[N<<2]; 20 struct S{ int l,r; }lp[N],rp[N]; 21 22 void add(int u,int
v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } 23 24 void work(int x,P p){ 25 if (p.op==1) v1[x]=v2[x]=(D){0,p.x}; 26 if (p.op==2) v1[x]=v2[x]=(D){p.x,-1}; 27 if (p.op==3) v1[x]=v2[x]=(D){p.x,p.x^(-1)}; 28 } 29 30 D operator +(D a,D b){ return (D){((~a.s0)&b.s0)|(a.s0&b.s1),((~a.s1)&b.s0)|(a.s1&b.s1)}; } 31 void upd(int x){ v1[x]=v1[ls]+v1[rs]; v2[x]=v2[rs]+v2[ls]; } 32 33 void dfs(int x){ 34 sz[x]=1; dep[x]=dep[fa[x]]+1; 35 For(i,x) if ((k=to[i])!=fa[x]){ 36 fa[k]=x; dfs(k); sz[x]+=sz[k]; 37 if (sz[k]>sz[son[x]]) son[x]=k; 38 } 39 } 40 41 void dfs2(int x,int tp){ 42 top[x]=tp; dfn[x]=++tim; pos[tim]=x; 43 if (son[x]) dfs2(son[x],tp); 44 For(i,x) if ((k=to[i])!=fa[x] && k!=son[x]) dfs2(k,k); 45 } 46 47 void build(int x,int L,int R){ 48 if (L==R){ work(x,p[pos[L]]); return; } 49 int mid=(L+R)>>1; 50 build(lson); build(rson); upd(x); 51 } 52 53 void mdf(int x,int L,int R,int pos,P p){ 54 if (L==R){ work(x,p); return; } 55 int mid=(L+R)>>1; 56 if (pos<=mid) mdf(lson,pos,p); else mdf(rson,pos,p); 57 upd(x); 58 } 59 60 D que(int x,int L,int R,int l,int r,int k){ 61 if (L==l && r==R) return (k==1) ? v1[x] : v2[x]; 62 int mid=(L+R)>>1; 63 if (r<=mid) return que(lson,l,r,k); 64 else if (l>mid) return que(rson,l,r,k); 65 else{ 66 D a=que(lson,l,mid,k),b=que(rson,mid+1,r,k); 67 return (k==1) ? a+b : b+a; 68 } 69 } 70 71 void solve(int x,int y,ll z){ 72 int ld=0,rd=0,rev=0; 73 S *L=lp,*R=rp; 74 for (; top[x]!=top[y]; x=fa[top[x]]){ 75 if (dep[top[x]]<dep[top[y]]) rev^=1,swap(x,y),swap(ld,rd),swap(L,R); 76 L[++ld]=(S){dfn[top[x]],dfn[x]}; 77 } 78 if (dep[x]<dep[y]) rev^=1,swap(x,y),swap(ld,rd),swap(L,R); 79 L[++ld]=(S){dfn[y],dfn[x]}; 80 if (rev) swap(ld,rd),swap(L,R); 81 D res=(D){0,-1}; 82 rep(i,1,ld) res=res+que(1,1,n,L[i].l,L[i].r,2); 83 for (int i=rd; i; i--) res=res+que(1,1,n,R[i].l,R[i].r,1); 84 ll s=0,c=0; 85 for (int i=k-1; ~i; i--) 86 if (res.s0&(I<<i)) s+=I<<i; 87 else if ((res.s1&(I<<i)) && c+(I<<i)<=z) c+=I<<i,s+=I<<i; 88 printf("%llu\n",s); 89 } 90 91 int main(){ 92 freopen("bzoj4811.in","r",stdin); 93 freopen("bzoj4811.out","w",stdout); 94 scanf("%d%d%d",&n,&m,&k); 95 rep(i,1,n) scanf("%d%llu",&p[i].op,&p[i].x); 96 rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u); 97 dfs(1); dfs2(1,1); build(1,1,n); 98 rep(i,1,m){ 99 scanf("%d%d%d%llu",&op,&x,&y,&z); 100 if (op==1) solve(x,y,z); else mdf(1,1,n,dfn[x],(P){y,z}); 101 } 102 return 0; 103 }