[BZOJ4129]Haruna’s Breakfast(树上带修改莫队)
BZOJ3585,BZOJ2120,BZOJ3757三合一。
对于树上路径问题,树链剖分难以处理的时候,就用树上带修改莫队。
这里的MEX问题,使用BZOJ3585的分块方法,平衡了时间复杂度。
剩下的就是将分块、树上莫队、带修改莫队合在一起了。大概要实现一下几个函数:
插入某值、删除某值、查询MEX、加入一个修改操作、更改一个点产生的影响(可能加入可能删除)。
另外要注意两个经典易错处:修改操作要记录lst以方便撤销,lst初始就是读入的数值。左端点所在块编号比右端点大是交换左右端点。
1 #include<cmath> 2 #include<cstdio> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 5 #define For(i,x) for (int i=h[x],k; i; i=nxt[i]) 6 using namespace std; 7 8 const int N=100010; 9 int n,m,op,u,v,A,B,p[N],bel[N],vis[N],val[N],w[N],lst[N],ans[N],fa[N][20]; 10 int cnt,top,bl,tot,s[510][510],stk[N],d[N],h[N],to[N<<1],nxt[N<<1]; 11 struct P{ int op,x,y,t,lst,id; }a[N],b[N]; 12 13 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } 14 15 bool cmp(const P &a,const P &b){ 16 if (bel[a.x]!=bel[b.x]) return bel[a.x]<bel[b.x]; 17 if (bel[a.y]!=bel[b.y]) return bel[a.y]<bel[b.y]; 18 return a.t<b.t; 19 } 20 21 void dfs(int x){ 22 d[x]=d[fa[x][0]]+1; int tmp=top; 23 rep(i,1,18) fa[x][i]=fa[fa[x][i-1]][i-1]; 24 For(i,x) if ((k=to[i])!=fa[x][0]){ 25 fa[k][0]=x; dfs(k); 26 if (top-tmp>=bl){ tot++; while (top>tmp) bel[stk[top--]]=tot; } 27 } 28 stk[++top]=x; 29 } 30 31 int lca(int x,int y){ 32 if (d[x]<d[y]) swap(x,y); 33 int t=d[x]-d[y]; 34 for (int i=18; ~i; i--) if (t&(1<<i)) x=fa[x][i]; 35 if (x==y) return x; 36 for (int i=18; ~i; i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 37 return fa[x][0]; 38 } 39 40 void add(int x){ 41 if (x>n) return; 42 int t=x%bl; s[p[x]][t]++; if (s[p[x]][t]==1) w[p[x]]++; 43 } 44 45 void del(int x){ 46 if (x>n) return; 47 int t=x%bl; s[p[x]][t]--; if (s[p[x]][t]==0) w[p[x]]--; 48 } 49 50 int que(){ 51 rep(i,1,n/bl+1){ 52 if (w[i]==bl) continue; 53 rep(j,(i-1)*bl,i*bl-1) if (!s[i][j%bl]) return j; 54 } 55 return (n/bl+1)*bl; 56 } 57 58 void mdf(int x,int y){ 59 if (!vis[x]){ val[x]=y; return; } 60 del(val[x]); val[x]=y; add(val[x]); 61 } 62 63 void upd(int x){ vis[x]?del(val[x]):add(val[x]); vis[x]^=1; } 64 65 void work(int x,int y){ 66 for (; x!=y; upd(x),x=fa[x][0]) 67 if (d[x]<d[y]) swap(x,y); 68 } 69 70 void solve(){ 71 int L=1,R=1,t=0; 72 rep(i,1,A){ 73 while (t>a[i].t) mdf(b[t].x,b[t].lst),t--; 74 while (t<a[i].t) t++,mdf(b[t].x,b[t].y); 75 work(L,a[i].x); work(R,a[i].y); L=a[i].x; R=a[i].y; 76 int f=lca(L,R); upd(f); ans[a[i].id]=que(); upd(f); 77 } 78 } 79 80 int main(){ 81 freopen("bzoj4129.in","r",stdin); 82 freopen("bzoj4129.out","w",stdout); 83 scanf("%d%d",&n,&m); p[0]=1; bl=sqrt(n); 84 rep(i,1,n) scanf("%d",&val[i]),lst[i]=val[i],p[i]=i/bl+1; 85 rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u); 86 dfs(1); while (top) bel[stk[top--]]=tot; 87 rep(i,1,m){ 88 scanf("%d%d%d",&op,&u,&v); 89 if (op==1){ 90 a[++A]=(P){op,u,v,B,0,A}; 91 if (bel[u]>bel[v]) swap(a[A].x,a[A].y); 92 }else b[++B]=(P){op,u,v,B,lst[u],0},lst[u]=v; 93 } 94 sort(a+1,a+A+1,cmp); solve(); 95 rep(i,1,A) printf("%d\n",ans[i]); 96 return 0; 97 }