zoukankan      html  css  js  c++  java
  • [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
    ",ans[i]);
    96     return 0;
    97 }
  • 相关阅读:
    objective-c 自定义归档
    GitHub---最简单的使用
    objective-c 单例
    objective-c 通知(Notification)
    objective-c 谓词
    objective-c KVO
    objective-c KVC
    objective-c 协议(Protocol)和代理(Delegate)
    Xcode一些方便的快捷键
    objective-c 类目(Category)和延展(Extension)
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10408893.html
Copyright © 2011-2022 走看看