[bzoj4129] Haruna’s Breakfast
树上莫队+分块。。
求mex的时候就上O(1)修改,O(根号n)查询的分块大法。。。
然后就套树上莫队模版。。我写的是括号序列的姿势。
莫队时的L和R有两种姿势。。
一种是莫队时的L和R表示[1,L]和[1,R]。。也就是根到两个查询节点的两条路径。显然lca一定会被消掉,所以计算答案前补回来。
第二种是莫队时的L和R表示[L,R]。。需要进行一些分类讨论>_<(具体见其他各路题解
我这种脑子不够用的蒟蒻肯定是写第一种啦。。。虽然并没有太大区别= =
数据显然是随机构造的。。所以怎么跑都能过= =。一开始块的大小取成了1竟然3s过
实测树上莫队块的大小取70~100有奇效。。。(这数据强度和糖果公园的比起来简直。。
(试了半天块的大小233
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=50233; 7 const int kuai=99,kuai2=323; 8 struct ask{ 9 int l,r,t,id; 10 }q[maxn];int qnum; 11 struct modi{ 12 int p,v,pre; 13 }c[maxn];int cnum; 14 struct zs{ 15 int too,pre; 16 }e[maxn<<1];int tot,last[maxn]; 17 int sz[maxn],fa[maxn],dep[maxn],bel[maxn],L[maxn],R[maxn]; 18 int pos[maxn<<1],B[maxn<<1],tim; 19 int cnt[maxn],sm[maxn]; 20 int v[maxn],pre[maxn]; 21 bool u[maxn]; 22 int i,j,k,n,m; 23 int an[maxn]; 24 25 int ra;char rx; 26 inline int read(){ 27 rx=getchar(),ra=0; 28 while(rx<'0'||rx>'9')rx=getchar(); 29 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 30 } 31 void dfs1(int x){ 32 sz[x]=1,dep[x]=dep[fa[x]]+1; 33 for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]) 34 fa[e[i].too]=x,dfs1(e[i].too),sz[x]+=sz[e[i].too]; 35 } 36 void dfs2(int x,int chain){ 37 int i,mx=0; 38 pos[L[x]=++tim]=x,bel[x]=chain; 39 for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&sz[e[i].too]>sz[mx])mx=e[i].too; 40 if(!mx){pos[R[x]=++tim]=x;return;} 41 dfs2(mx,chain); 42 for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&e[i].too!=mx)dfs2(e[i].too,e[i].too); 43 pos[R[x]=++tim]=x; 44 } 45 inline int getlca(int a,int b){ 46 while(bel[a]!=bel[b]){ 47 if(dep[bel[a]]<dep[bel[b]])swap(a,b); 48 a=fa[bel[a]]; 49 } 50 return dep[a]<dep[b]?a:b; 51 } 52 53 inline void vis(int x){ 54 if(v[x]<=n) 55 if(u[x]) 56 if(--cnt[v[x]]==0)sm[v[x]/kuai2]--; 57 else; 58 else if(cnt[v[x]]++==0)sm[v[x]/kuai2]++; 59 u[x]^=1; 60 } 61 inline void change(int x,int y){ 62 if(u[x])vis(x),v[x]=y,vis(x);else v[x]=y; 63 } 64 inline int query(){ 65 int i=0; 66 while(sm[i]==kuai2)i++; 67 for(i*=kuai2;cnt[i];i++); 68 return i; 69 } 70 71 bool cmp(ask a,ask b){ 72 return B[a.l]<B[b.l]||(B[a.l]==B[b.l]&&B[a.r]<B[b.r])||(B[a.l]==B[b.l]&&B[a.r]==B[b.r]&&a.t<b.t); 73 } 74 inline void insert(int a,int b){ 75 e[++tot].too=b,e[tot].pre=last[a],last[a]=tot; 76 e[++tot].too=a,e[tot].pre=last[b],last[b]=tot; 77 } 78 int main(){ 79 n=read(),m=read(); 80 for(i=1;i<=n;i++)v[i]=pre[i]=read(); 81 for(i=1;i<n;i++)j=read(),insert(j,read()); 82 dfs1(1),dfs2(1,1); 83 84 int id; 85 for(i=1;i<=m;i++){ 86 id=read(),j=read(),k=read(); 87 if(!id)c[++cnum]=(modi){j,k,pre[j]},pre[j]=k;else{ 88 if(L[j]>L[k])swap(j,k); 89 q[++qnum]=(ask){L[j],L[k],cnum,qnum}; 90 } 91 } 92 for(i=1;i<=tim;i++)B[i]=(i+kuai-1)/kuai; 93 sort(q+1,q+1+qnum,cmp); 94 95 int l=1,r=1,t=0,lca,x,y; 96 for(i=1;i<=qnum;i++){ 97 while(t<q[i].t)t++,change(c[t].p,c[t].v); 98 while(t>q[i].t)change(c[t].p,c[t].pre),t--; 99 while(l>q[i].l)vis(pos[l--]); 100 while(r>q[i].r)vis(pos[r--]); 101 while(l<q[i].l)vis(pos[++l]); 102 while(r<q[i].r)vis(pos[++r]); 103 104 x=pos[l],y=pos[r],lca=getlca(x,y), 105 vis(lca), 106 107 an[q[i].id]=query(), 108 vis(lca); 109 } 110 for(i=1;i<=qnum;i++)printf("%d\n",an[i]); 111 return 0; 112 }