BZOJ4129: Haruna’s Breakfast

http://www.lydsy.com/JudgeOnline/problem.php?id=4129

  树上带修改求mex,树上带修改莫队即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=50015,maxe=100015,maxm=50015,maxb=255,maxk=20;
int n,m,ask,tim,a[maxn];
struct Tmodify{int x,v;}M[maxm];
struct Tquery{int idx,u,v,t;}Q[maxm];
int tot,now[maxn],pre[maxe],son[maxe];
void connect(int u,int v){pre[++tot]=now[u];now[u]=tot;son[tot]=v;}
void init(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i) scanf("%d",&a[i]);
    for (int u,v,i=1;i<=n-1;++i){
        scanf("%d%d",&u,&v);
        connect(u,v);connect(v,u);
    }
    for (int t,u,v,i=1;i<=m;++i){
        scanf("%d%d%d",&t,&u,&v);
        switch (t){
            case 0:M[++tim]=(Tmodify){u,v};break;
            case 1:Q[++ask]=(Tquery){ask,u,v,tim};break;
        }
    }
}
int dep[maxn],anc[maxn][maxk];
void get_anc(int u,int f){
    anc[u][0]=f;dep[u]=dep[f]+1;
    for (int k=1;k<maxk;++k) anc[u][k]=anc[anc[u][k-1]][k-1];
    for (int p=now[u];p;p=pre[p]) if (son[p]!=f) get_anc(son[p],u);
}
int siz1,top,cnt,stk[maxn],bel[maxn];
void get_block(int u,int f){
    for (int bot=top,p=now[u];p;p=pre[p]){
        if (son[p]==f) continue;get_block(son[p],u);
        if (top-bot>=siz1) for (++cnt;top!=bot;bel[stk[top--]]=cnt);
    }
    stk[++top]=u;
}
bool cmp(Tquery a,Tquery b){
    if (bel[a.u]!=bel[b.u]) return bel[a.u]<bel[b.u];
    else if (bel[a.v]!=bel[b.v]) return bel[a.v]<bel[b.v];
    else return a.t<b.t;
}
void prepare(){
    siz1=pow(n,0.67);
    get_anc(1,0);get_block(1,0);
    while (top) bel[stk[top--]]=cnt;
    for (int i=1;i<=ask;++i) if (bel[Q[i].u]>bel[Q[i].v]) swap(Q[i].u,Q[i].v);
    sort(Q+1,Q+ask+1,cmp);
}
bool exist[maxn];
int num,siz2,ans[maxm],bl[maxb],br[maxb],have[maxb],idx[maxn],sum[maxn];
void xor_node(int u){
    if (exist[u]){if (a[u]<=n) if (!--sum[a[u]]) --have[idx[a[u]]];}
    else if (a[u]<=n) if (!sum[a[u]]++) ++have[idx[a[u]]];
    exist[u]^=1;
}
void xor_path(int u,int v){
    if (dep[u]<dep[v]) swap(u,v);
    while (dep[u]!=dep[v]){xor_node(u);u=anc[u][0];}
    while (u!=v){xor_node(u);xor_node(v);u=anc[u][0];v=anc[v][0];}
}
void modify(int t){
    int x=M[t].x,v=M[t].v;
    if (exist[x]){
        if (a[x]<=n) if (!--sum[a[x]]) --have[idx[a[x]]];
        if (v<=n) if (!sum[v]++) ++have[idx[v]];
    }
    swap(M[t].v,a[x]);
}
void move_time(int ever,int now){
    for (int i=ever+1;i<=now;++i) modify(i);
    for (int i=ever;i>=now+1;--i) modify(i);
}
int lca(int u,int v){
    if (dep[u]<dep[v]) swap(u,v);
    for (int h=dep[u]-dep[v],i=0;h;h>>=1,++i) if (h&1) u=anc[u][i];
    for (int k=maxk-1;k>=0;--k) if (anc[u][k]!=anc[v][k]){u=anc[u][k];v=anc[v][k];}
    return u==v?u:anc[u][0];
}
int get_ans(){
    int pos,res;
    for (pos=0;have[pos]==siz2;++pos);
    for (res=bl[pos];sum[res];++res);
    return res;
}
void solve(int k){
    xor_path(Q[k-1].u,Q[k].u);
    xor_path(Q[k-1].v,Q[k].v);
    move_time(Q[k-1].t,Q[k].t);
    int x=lca(Q[k].u,Q[k].v);
    xor_node(x);ans[Q[k].idx]=get_ans();xor_node(x);
}
void work(){
    prepare();siz2=sqrt(n);
    for (int j,i=0;i<=n;i=j,++num){
        for (j=i;j-i+1<=siz2&&j<=n;++j) idx[j]=num;
        bl[num]=i;br[num]=j-1;
    }
    for (int i=1;i<=ask;++i) solve(i);
    for (int i=1;i<=ask;++i) printf("%d
",ans[i]);
}
int main(){
    init();
    work();
    return 0;
}
my code
原文地址:https://www.cnblogs.com/iamCYY/p/4720029.html