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 }
View Code

 

posted @ 2018-07-11 16:39  lyf2  阅读(178)  评论(0编辑  收藏  举报