bzoj 4129: Haruna’s Breakfast
4129: Haruna’s Breakfast
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 997 Solved: 471
[Submit][Status][Discuss]
Description
Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了一棵
树上,每个结点都有一样食材,Shimakaze要考验一下她。
每个食材都有一个美味度,Shimakaze会进行两种操作:
1、修改某个结点的食材的美味度。
2、对于某条链,询问这条链的美味度集合中,最小的未出现的自然数是多少。即mex值。
请你帮帮Haruna吧。
Input
第一行包括两个整数n,m,代表树上的结点数(标号为1~n)和操作数。
第二行包括n个整数a1...an,代表每个结点的食材初始的美味度。
接下来n-1行,每行包括两个整数u,v,代表树上的一条边。
接下来m 行,每行包括三个整数
0 u x 代表将结点u的食材的美味度修改为 x。
1 u v 代表询问以u,v 为端点的链的mex值。
Output
对于每次询问,输出该链的mex值。
Sample Input
10 10
1 0 1 0 2 4 4 0 1 0
1 2
2 3
2 4
2 5
1 6
6 7
2 8
3 9
9 10
0 7 14
1 6 6
0 4 9
1 2 2
1 1 8
1 8 3
0 10 9
1 3 5
0 10 0
0 7 7
1 0 1 0 2 4 4 0 1 0
1 2
2 3
2 4
2 5
1 6
6 7
2 8
3 9
9 10
0 7 14
1 6 6
0 4 9
1 2 2
1 1 8
1 8 3
0 10 9
1 3 5
0 10 0
0 7 7
Sample Output
0
1
2
2
3
1
2
2
3
HINT
1<=n<=5*10^4
1<=m<=5*10^4
0<=ai<=10^9
#include <bits/stdc++.h> #define ll long long #define pii pair<int,int> const int MAXN=5e4+10; const int inf=5e4+5; using namespace std; ll readll(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int readint(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int n,m,size,p[MAXN<<1],c[MAXN]; ll a[MAXN];pii Next[MAXN<<1],to[MAXN],past[MAXN]; int first[MAXN],cnt1,size1; void add(int u,int v){ Next[++cnt1].first=first[u];Next[cnt1].second=v;first[u]=cnt1; Next[++cnt1].first=first[v];Next[cnt1].second=u;first[v]=cnt1; } int b[MAXN<<1],begin[MAXN],last[MAXN],cnt,num[MAXN],son[MAXN],fa[MAXN],dep[MAXN]; void dfs1(int v,int pre,int deep){ b[++cnt]=v;begin[v]=cnt;num[v]=1;dep[v]=deep+1;fa[v]=pre; for(int i=first[v];i!=-1;i=Next[i].first){ int u=Next[i].second; if(u!=pre){ dfs1(u,v,deep+1); num[v]+=num[u]; if(son[v]==-1||num[son[v]]<num[u]) son[v]=u; } } b[++cnt]=v;last[v]=cnt; } int tp[MAXN]; void dfs2(int v,int td){ tp[v]=td; if(son[v]!=-1) dfs2(son[v],td); for(int i=first[v];i!=-1;i=Next[i].first){ int u=Next[i].second; if(u!=fa[v]&&u!=son[v]) dfs2(u,u); } } int Lca(int u,int v){ int uu=tp[u];int vv=tp[v]; while(uu!=vv){ if(dep[uu]<dep[vv]){ swap(uu,vv);swap(u,v); } u=fa[uu];uu=tp[u]; } if(dep[u]>dep[v]) swap(u,v); return u; } typedef struct node{ int l,r,t,biao,lca,flag; friend bool operator <(node aa,node bb){ if(p[aa.l]==p[bb.l]&&p[aa.r]==p[bb.r]) return aa.t<bb.t; else if(p[aa.l]==p[bb.l]) return p[aa.r]<p[bb.r]; else return p[aa.l]<p[bb.l]; } }node; node d[MAXN];int kuai[1005];int cont[inf],pp[inf],vis[MAXN]; void update(int l,int r,int t){ int u=to[t].first;int vul=to[t].second; int t1=begin[u];int t2=last[u];int cp=0;int pos; if(t1>=l&&t1<=r) cp++,pos=t1; if(t2>=l&&t2<=r) cp++,pos=t2; if(cp==1){ if(vul+1<inf){ if(a[b[pos]]+1<inf){ cont[a[b[pos]]+1]--; if(!cont[a[b[pos]]+1]) kuai[pp[a[b[pos]]+1]]--; } cont[vul+1]++; if(cont[vul+1]==1) kuai[pp[vul+1]]++; } } a[u]=vul; } void restore(int l,int r,int t){ int u=past[t].first;int vul=past[t].second; int t1=begin[u];int t2=last[u];int cp=0;int pos; if(t1>=l&&t1<=r) cp++,pos=t1; if(t2>=l&&t2<=r) cp++,pos=t2; if(cp==1){ if(vul+1<inf){ if(a[b[pos]+1]<inf){ cont[a[b[pos]]+1]--; if(!cont[a[b[pos]]+1]) kuai[pp[a[b[pos]]+1]]--; } cont[vul+1]++; if(cont[vul+1]==1) kuai[pp[vul+1]]++; } } a[u]=vul; } void work(int pos){ vis[b[pos]]^=1; if(vis[b[pos]]){ if(a[b[pos]]+1<inf){ cont[a[b[pos]]+1]++; if(cont[a[b[pos]]+1]==1) kuai[pp[a[b[pos]]+1]]++; } } else{ if(a[b[pos]]+1<inf){ cont[a[b[pos]]+1]--; if(!cont[a[b[pos]]+1]) kuai[pp[a[b[pos]]+1]]--; } } } int querty(){ for(int i=1;i<pp[inf-1];i++){ if(kuai[i]==size1) continue; for(int j=(i-1)*size1+1;j<=i*size1;j++){ if(!cont[j]) return j; } } for(int i=(pp[inf-1]-1)*size1+1;i<inf;i++){ if(!cont[i]) return i; } } int ans[MAXN]; void print(){ cout<<"======="<<endl; for(int i=1;i<=pp[inf-1];i++){ if(!kuai[i]) break; printf("%d ",kuai[i]); } cout<<endl; } int main(){ ios::sync_with_stdio(false); n=readint();m=readint();size=(int)pow(n*2,2.0/3); size1=(int)sqrt(inf-1); for(int i=1;i<=2*n;i++) p[i]=(i-1)/size+1; for(int i=1;i<inf;i++) pp[i]=(i-1)/size1+1; for(int i=1;i<=n;i++) son[i]=first[i]=-1; for(int i=1;i<=n;i++) c[i]=a[i]=readll(); int u,v,l,r,op;ll x; for(int i=1;i<n;i++) u=readint(),v=readint(),add(u,v); dfs1(1,-1,0);dfs2(1,1);int T=0;int uu=0; // for(int i=1;i<=2*n;i++) cout<<b[i]<<" "; // cout<<endl; for(int i=1;i<=m;i++){ op=readint(); if(op==0){ l=readint();x=readll(); to[++T].first=l;to[T].second=x; past[T].first=l;past[T].second=c[l]; c[l]=x; } else{ l=readint();r=readint();d[++uu].biao=uu;d[uu].lca=Lca(l,r);d[uu].t=T; if(d[uu].lca==l||d[uu].lca==r) d[uu].l=min(begin[l],begin[r]),d[uu].r=max(begin[l],begin[r]); else{ if(begin[l]>begin[r]) swap(l,r); d[uu].l=last[l];d[uu].r=begin[r];d[uu].flag=1; } } } sort(d+1,d+uu+1); // for(int i=1;i<=uu;i++) cout<<d[i].l<<" "<<d[i].r<<" "<<d[i].biao<<" "<<d[i].t<<" "<<d[i].lca<<endl; int L=1,R=0;T=0; for(int i=1;i<=uu;i++){ while(T>d[i].t){ restore(L,R,T);T--; } while(T<d[i].t){ T++;update(L,R,T); } while(R>d[i].r){ work(R);R--; } while(R<d[i].r){ R++;work(R); } while(L<d[i].l){ work(L);L++; } while(L>d[i].l){ L--;work(L); } if(d[i].flag&&a[d[i].lca]+1<inf){ cont[a[d[i].lca]+1]++; if(cont[a[d[i].lca]+1]==1) kuai[pp[a[d[i].lca]+1]]++; } ans[d[i].biao]=querty(); if(d[i].flag&&a[d[i].lca]+1<inf){ cont[a[d[i].lca]+1]--; if(!cont[a[d[i].lca]+1]) kuai[pp[a[d[i].lca]+1]]--; } // print(); } for(int i=1;i<=uu;i++) printf("%d\n",ans[i]-1); return 0; }