BZOJ4129: Haruna’s Breakfast
看起来像是树上莫队的样子qwq
mex要怎么维护?
我们可以考虑用分块
显然的mex最大为n+1
我们分快的下标表示一段权之间的数字
查询找找没有满的块的好了,显然mex就在里面了
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 const int N=5*10000+10; 7 int v[N*2],nxt[N*2],first[N],cnt; 8 int dep[N],fa[N],siz[N],dp[N][20],dfn[N],tim,h; 9 int st[N],top,sz,bl[N],blo; 10 int b[N],fk[N],l[N],r[N]; 11 int num[N],c[N],las[N]; 12 int n,m,ans[N]; 13 bool vis[N]; 14 struct n1{ 15 int u,v,id,t; 16 bool operator < (const n1&x) const { 17 if(bl[u]==bl[x.u]&&bl[v]==bl[x.v]) return t<x.t; 18 if(bl[u]==bl[x.u]) return bl[v]<bl[x.v]; 19 return bl[u]<bl[x.u]; 20 } 21 }cx[N]; 22 struct n2{ 23 int u,pre,sub; 24 }xg[N]; 25 26 void read(int &x){ 27 x=0;int f=1;char c=getchar(); 28 while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();} 29 while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();} 30 x*=f; 31 } 32 33 void add(int a,int b){ 34 v[++cnt]=b; 35 nxt[cnt]=first[a]; 36 first[a]=cnt; 37 } 38 39 void dfs(int x){ 40 dp[x][0]=fa[x]; 41 st[++top]=x;dfn[x]=++tim; 42 for(int i=1;i<=h;i++) dp[x][i]=dp[dp[x][i-1]][i-1]; 43 for(int i=first[x];i;i=nxt[i]){ 44 if(fa[x]==v[i]) continue; 45 dep[v[i]]=dep[x]+1; 46 fa[v[i]]=x; 47 dfs(v[i]); 48 if(siz[x]+siz[v[i]]>=blo){ 49 ++sz; 50 while(x!=st[top]) bl[st[top--]]=sz; 51 siz[x]=0; 52 } 53 else siz[x]+=siz[v[i]]; 54 } 55 ++siz[x]; 56 } 57 58 int lca(int x,int y){ 59 if(dep[x]<dep[y]) swap(x,y); 60 for(int i=h;i>=0;i--) if(dep[dp[x][i]]>=dep[y]) x=dp[x][i]; 61 if(x==y) return x; 62 for(int i=h;i>=0;i--) 63 if(dp[x][i]!=dp[y][i]){ 64 x=dp[x][i]; 65 y=dp[y][i]; 66 } 67 return dp[x][0]; 68 } 69 70 void make(){ 71 int p=sqrt(m); 72 int sqr=0; 73 if(m%p) sqr=m/p+1; 74 else sqr=m/p; 75 for(int i=1;i<=m;i++) b[i]=(i-1)/p+1; 76 for(int i=1;i<=sqr;i++) l[i]=(i-1)*p+1,r[i]=i*p; 77 r[sqr]=m; 78 } 79 80 void ud(int u){ 81 if(c[u]<=m){ 82 if(vis[u]){ 83 num[c[u]]--; 84 if(num[c[u]]==0) fk[b[c[u]]]--; 85 } 86 else { 87 if(num[c[u]]==0) fk[b[c[u]]]++; 88 num[c[u]]++; 89 } 90 } 91 vis[u]^=1; 92 } 93 94 void change(int x,int y){ 95 if(vis[x]){ 96 ud(x); 97 c[x]=y; 98 ud(x); 99 } 100 else c[x]=y; 101 } 102 103 void sol(int x,int y){ 104 while(x!=y){ 105 if(dep[x]>dep[y]) ud(x),x=fa[x]; 106 else ud(y),y=fa[y]; 107 } 108 } 109 110 int query(){ 111 int k=1; 112 while(fk[k]==r[k]-l[k]+1) k++; 113 int ans=l[k]; 114 while(num[ans]) ans++; 115 return ans-1; 116 } 117 118 int main(){ 119 int k; 120 read(n);read(k);m=n+1; 121 h=log2(n);blo=pow(n,2.0/3); 122 make(); 123 for(int i=1;i<=n;i++) read(c[i]),++c[i],las[i]=c[i]; 124 for(int i=1;i<n;i++){ 125 int x,y; 126 read(x);read(y); 127 add(x,y);add(y,x); 128 } 129 dfs(1);dep[0]=-1; 130 while(top) bl[st[top--]]=sz; 131 int a1=0,a2=0; 132 for(int i=1;i<=k;i++){ 133 int x,y,z; 134 read(x);read(y);read(z); 135 if(x){ 136 if(dfn[y]>dfn[z]) swap(z,y); 137 cx[++a1].u=y;cx[a1].v=z;cx[a1].id=a1;cx[a1].t=a2; 138 } 139 else { 140 ++z;++a2; 141 xg[a2].u=y;;xg[a2].pre=las[y];xg[a2].sub=z; 142 las[y]=z; 143 } 144 } 145 sort(cx+1,cx+1+a1); 146 int lc=0,t=0; 147 for(int i=1;i<=a1;i++){ 148 while(t>cx[i].t) change(xg[t].u,xg[t].pre),t--; 149 while(t<cx[i].t) change(xg[t+1].u,xg[t+1].sub),t++; 150 sol(cx[i-1].u,cx[i].u);sol(cx[i-1].v,cx[i].v); 151 lc=lca(cx[i].u,cx[i].v);ud(lc); 152 ans[cx[i].id]=query();ud(lc); 153 } 154 for(int i=1;i<=a1;i++) printf("%d\n",ans[i]); 155 return 0; 156 }