BZOJ 4129 Haruna’s Breakfast
阿新 • • 發佈:2018-12-03
同樣是樹上莫隊
只不過要求一個集合的mex,這裡可以使用分塊,可以在根號時間內得出解
/************************************************** Problem: 4129 User: star_magic_young Language: C++ Result: Accepted Time:748 ms Memory:8712 kb ****************************************************/ #include<bits/stdc++.h> #define LL long long #define il inline #define re register using namespace std; const int N=50000+10; il int rd() { int x=0,w=1;char ch=0; while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*w; } int n,m,q,szm,mm[N],ti,mdf[N][3],a[N]; int na,an[N]; int to[N<<1],nt[N<<1],hd[N],tot=1,st[N],tp,fa[N],sz[N],de[N],son[N],top[N]; bool v[N]; il void add(int x,int y) { ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot; ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot; } void dfs1(int x) { sz[x]=1; int la=tp; for(int i=hd[x];i;i=nt[i]) { int y=to[i]; if(y==fa[x]) continue; fa[y]=x,de[y]=de[x]+1,dfs1(y),sz[x]+=sz[y]; if(sz[son[x]]<sz[y]) son[x]=y; if(tp-la>=szm){++m;while(tp!=la) mm[st[tp--]]=m;} } st[++tp]=x; } void dfs2(int x,int ntp) { top[x]=ntp; if(son[x]) dfs2(son[x],ntp); for(int i=hd[x];i;i=nt[i]) { int y=to[i]; if(y==fa[x]||y==son[x]) continue; dfs2(y,y); } } il int glca(int x,int y) { while(top[x]!=top[y]) { if(de[top[x]]<de[top[y]]) swap(x,y); x=fa[top[x]]; } return de[x]<de[y]?x:y; } int b[N],sm[400],ll[400],rr[400],sq,tt=-1; il void upd(int x) { v[x]^=1; if(a[x]<=n) { if(v[x]) sm[a[x]/sq]+=(++b[a[x]]==1); else sm[a[x]/sq]-=(--b[a[x]]==0); } } il int gans() { for(int i=0;i<=tt;++i) if(sm[i]!=rr[i]-ll[i]+1) { for(int j=ll[i];j<=rr[i];++j) if(!b[j]) return j; } return 1******7; } il void mv(int x,int y) { if(x==y) return; if(de[x]<de[y]) swap(x,y); while(de[x]>de[y]) { upd(x),x=fa[x]; } while(x!=y) { upd(x),x=fa[x]; upd(y),y=fa[y]; } //upd(x); } struct qu { int l,r,t,id; bool operator < (const qu &bb) const {return mm[l]!=mm[bb.l]?mm[l]<mm[bb.l]:(mm[r]!=mm[bb.r]?mm[r]<mm[bb.r]:t<bb.t);} }qq[N]; int main() { n=rd(),q=rd(); szm=(int)pow(n,0.45); sq=sqrt(n); for(int i=0;i<=n;i+=sq) ll[++tt]=i,rr[tt]=i+sq-1; rr[tt]=min(rr[tt],n); for(int i=1;i<=n;++i) a[i]=rd(); for(int i=1;i<n;++i) add(rd(),rd()); dfs1(1); ++m;while(tp) mm[st[tp--]]=m; dfs2(1,1); for(int i=1;i<=q;++i) { int op=rd(); if(op) { qq[i-ti].l=rd(),qq[i-ti].r=rd(),qq[i-ti].t=ti,qq[i-ti].id=i-ti; if(mm[qq[i-ti].l]>mm[qq[i-ti].r]) swap(qq[i-ti].l,qq[i-ti].r); } else mdf[++ti][0]=rd(),mdf[ti][1]=rd(); } sort(qq+1,qq+q-ti+1); for(int i=1,l=1,r=1,t=0;i<=q-ti;l=qq[i].l,r=qq[i].r,++i) { while(t<qq[i].t) { ++t; int xx=mdf[t][0],yy=mdf[t][1];mdf[t][2]=a[xx]; if(v[xx]) { if(a[xx]<=n) sm[a[xx]/sq]-=(--b[a[xx]]==0); if(yy<=n) sm[yy/sq]+=(++b[yy]==1); } a[xx]=yy; } while(t>qq[i].t) { int xx=mdf[t][0],yy=mdf[t][2]; if(v[xx]) { if(a[xx]<=n) sm[a[xx]/sq]-=(--b[a[xx]]==0); if(yy<=n) sm[yy/sq]+=(++b[yy]==1); } a[xx]=yy; --t; } mv(l,qq[i].l),mv(r,qq[i].r); int lca=glca(qq[i].l,qq[i].r); upd(lca),an[qq[i].id]=gans(),upd(lca); } for(int i=1;i<=q-ti;++i) printf("%d\n",an[i]); return 0; }