bzoj4129

题解:

树上+可修改莫队

莫队的每一块

可以用一个栈

每一次dfs个数>sqrt(n)(自己选的)的时候就可以跳出了

然后不要忘记分出来最后一块

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=400005;
int k=1,fi[N],unit,Be[N],m,st[N],top,fa[N][18],deep[N],n,Q;
int a[N],t[N],op,x,y,p,tim,u=1,v=1,T,ans[N],vis[N],ne[N],zz[N];
struct Change
{
    int u,New,Old;
}cq[N];
struct Query
{
    int u,v,tim,id;
    int operator <(const Query &a) const
     {
         if (Be[u]!=Be[a.u])return Be[u]<Be[a.u];
         if (Be[v]!=Be[a.v])return Be[v]<Be[a.v];
         return tim<a.tim;
     }
}q[N];
struct Datalook
{
    struct _bol{int l,r;}b[350];
    int n,Be[N],m,unit,num[N],sum[350];
    void init()
     {
         unit=sqrt(n);
         m=(n-1)/unit+1;
         for (int i=1;i<=n;i++)Be[i]=(i-1)/unit+1;
         for (int i=1;i<=m;i++)b[i].l=(i-1)*unit+1,b[i].r=i*unit;
         b[m].r=n;
     }
    void Add(int v)
     {
         if (v<=n)sum[Be[v]]+=(++num[v])==1;
     }
    void Del(int v)
     {
         if (v<=n)sum[Be[v]]-=(--num[v])==0;
     } 
    int mex()
     {
         for (int i=1;i<=m;i++)
          if (sum[i]!=b[i].r-b[i].l+1)
           for (int j=b[i].l;j<=b[i].r;j++)
            if (!num[j])return j;
         return -1;   
     } 
}Data;
void jb(int u,int v)
{
    ne[k]=fi[u];
    zz[k]=v;
    fi[u]=k++;
}
void dfs(int u)
{
    for (int i=1;i<=19;i++)
     if ((1<<i)>deep[u])break;
     else fa[u][i]=fa[fa[u][i-1]][i-1];
    int bottom=top;
    for (int i=fi[u];i;i=ne[i])
     {
         int v=zz[i];
         if (v!=fa[u][0])
          {
              fa[v][0]=u;
              deep[v]=deep[u]+1;
              dfs(v);
              if (top-bottom>=unit)
               {
                   m++;
                   while (top!=bottom)Be[st[top--]]=m;
               }
          }
     }
    st[++top]=u; 
}
int Lca(int x,int y)
{
    if (deep[x]<deep[y])swap(x,y);
    int Dis=deep[x]-deep[y];
    for (int i=0;i<=16;i++)
     if ((1<<i)&Dis)x=fa[x][i];
    if (x==y)return x;
    for (int i=16;i>=0;i--)
     if (fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return x==y?x:fa[x][0];  
}
void revise(int u,int d)
{
    if (vis[u])
     {
         Data.Del(a[u]);
         Data.Add(d);
     }
    a[u]=d; 
}
void run(int u)
{
    if (vis[u])
     {
         Data.Del(a[u]);
         vis[u]=0;
     }
    else 
     {
         Data.Add(a[u]);
         vis[u]=1;
     } 
}
void move(int x,int y)
{
    if (deep[x]<deep[y])swap(x,y);
    while (deep[x]>deep[y])run(x),x=fa[x][0];
    while (x!=y)run(x),run(y),x=fa[x][0],y=fa[y][0];
}
int main()
{
    scanf("%d%d",&n,&Q);
    for (int i=1;i<=n;i++)
     {
         scanf("%d",&a[i]);
         t[i]=++a[i];
     }
    for (int i=2;i<=n;i++)
     {
         scanf("%d%d",&x,&y);
         jb(x,y);jb(y,x);
     } 
    dfs(1);
    while (top)Be[st[top--]]=m;
    for (int i=1;i<=Q;i++)
     {
         scanf("%d%d%d",&op,&x,&y);
         if (op)q[++p]=(Query){x,y,tim,p};
         if (!op)cq[++tim]=(Change){x,y+1,t[x]},t[x]=y+1;
     } 
    Data.n=n+1;
    Data.init();
    sort(q+1,q+1+p);
    for (int i=1;i<=p;i++)
     {
        while (T<q[i].tim)T++,revise(cq[T].u,cq[T].New);
        while (T>q[i].tim)revise(cq[T].u,cq[T].Old),T--;
        if(u!=q[i].u)move(u,q[i].u),u=q[i].u;
        if(v!=q[i].v)move(v,q[i].v),v=q[i].v;
        int anc=Lca(u,v);
        run(anc);
        ans[q[i].id]=Data.mex()-1;
        run(anc);
     }
    for (int i=1;i<=p;i++)printf("%d
",ans[i]); 
}
原文地址:https://www.cnblogs.com/xuanyiming/p/8439734.html