[bzoj4129] Haruna’s Breakfast

  树上莫队+分块。。

  求mex的时候就上O(1)修改,O(根号n)查询的分块大法。。。

  然后就套树上莫队模版。。我写的是括号序列的姿势。

  莫队时的L和R有两种姿势。。

  一种是莫队时的L和R表示[1,L]和[1,R]。。也就是根到两个查询节点的两条路径。显然lca一定会被消掉,所以计算答案前补回来。

  第二种是莫队时的L和R表示[L,R]。。需要进行一些分类讨论>_<(具体见其他各路题解

  我这种脑子不够用的蒟蒻肯定是写第一种啦。。。虽然并没有太大区别= =

  数据显然是随机构造的。。所以怎么跑都能过= =。一开始块的大小取成了1竟然3s过

  实测树上莫队块的大小取70~100有奇效。。。(这数据强度和糖果公园的比起来简直。。

  (试了半天块的大小233

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int maxn=50233;
  7 const int kuai=99,kuai2=323;
  8 struct ask{
  9     int l,r,t,id;
 10 }q[maxn];int qnum;
 11 struct modi{
 12     int p,v,pre;
 13 }c[maxn];int cnum;
 14 struct zs{
 15     int too,pre;
 16 }e[maxn<<1];int tot,last[maxn];
 17 int sz[maxn],fa[maxn],dep[maxn],bel[maxn],L[maxn],R[maxn];
 18 int pos[maxn<<1],B[maxn<<1],tim;
 19 int cnt[maxn],sm[maxn];
 20 int v[maxn],pre[maxn];
 21 bool u[maxn];
 22 int i,j,k,n,m;
 23 int an[maxn];
 24  
 25 int ra;char rx;
 26 inline int read(){
 27     rx=getchar(),ra=0;
 28     while(rx<'0'||rx>'9')rx=getchar();
 29     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
 30 }
 31 void dfs1(int x){
 32     sz[x]=1,dep[x]=dep[fa[x]]+1;
 33     for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x])
 34         fa[e[i].too]=x,dfs1(e[i].too),sz[x]+=sz[e[i].too];
 35 }
 36 void dfs2(int x,int chain){
 37     int i,mx=0;
 38     pos[L[x]=++tim]=x,bel[x]=chain;
 39     for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&sz[e[i].too]>sz[mx])mx=e[i].too;
 40     if(!mx){pos[R[x]=++tim]=x;return;}
 41     dfs2(mx,chain);
 42     for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&e[i].too!=mx)dfs2(e[i].too,e[i].too);
 43     pos[R[x]=++tim]=x;
 44 }
 45 inline int getlca(int a,int b){
 46     while(bel[a]!=bel[b]){
 47         if(dep[bel[a]]<dep[bel[b]])swap(a,b);
 48         a=fa[bel[a]];
 49     }
 50     return dep[a]<dep[b]?a:b;
 51 }
 52  
 53 inline void vis(int x){
 54     if(v[x]<=n)
 55         if(u[x])
 56             if(--cnt[v[x]]==0)sm[v[x]/kuai2]--;
 57             else;
 58         else if(cnt[v[x]]++==0)sm[v[x]/kuai2]++;
 59     u[x]^=1;
 60 }
 61 inline void change(int x,int y){
 62     if(u[x])vis(x),v[x]=y,vis(x);else v[x]=y;
 63 }
 64 inline int query(){
 65     int i=0;
 66     while(sm[i]==kuai2)i++;
 67     for(i*=kuai2;cnt[i];i++);
 68     return i;
 69 }
 70  
 71 bool cmp(ask a,ask b){
 72     return B[a.l]<B[b.l]||(B[a.l]==B[b.l]&&B[a.r]<B[b.r])||(B[a.l]==B[b.l]&&B[a.r]==B[b.r]&&a.t<b.t);
 73 }
 74 inline void insert(int a,int b){
 75     e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;
 76     e[++tot].too=a,e[tot].pre=last[b],last[b]=tot;
 77 }
 78 int main(){
 79     n=read(),m=read();
 80     for(i=1;i<=n;i++)v[i]=pre[i]=read();
 81     for(i=1;i<n;i++)j=read(),insert(j,read());
 82     dfs1(1),dfs2(1,1);
 83      
 84     int id;
 85     for(i=1;i<=m;i++){
 86         id=read(),j=read(),k=read();
 87         if(!id)c[++cnum]=(modi){j,k,pre[j]},pre[j]=k;else{
 88             if(L[j]>L[k])swap(j,k);
 89             q[++qnum]=(ask){L[j],L[k],cnum,qnum};
 90         }
 91     }
 92     for(i=1;i<=tim;i++)B[i]=(i+kuai-1)/kuai;
 93     sort(q+1,q+1+qnum,cmp);
 94      
 95     int l=1,r=1,t=0,lca,x,y;
 96     for(i=1;i<=qnum;i++){
 97         while(t<q[i].t)t++,change(c[t].p,c[t].v);
 98         while(t>q[i].t)change(c[t].p,c[t].pre),t--;
 99         while(l>q[i].l)vis(pos[l--]);
100         while(r>q[i].r)vis(pos[r--]);
101         while(l<q[i].l)vis(pos[++l]);
102         while(r<q[i].r)vis(pos[++r]);
103          
104         x=pos[l],y=pos[r],lca=getlca(x,y),
105         vis(lca),
106          
107         an[q[i].id]=query(),
108         vis(lca);
109     }
110     for(i=1;i<=qnum;i++)printf("%d
",an[i]);
111     return 0;
112 }
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5395188.html