zoukankan      html  css  js  c++  java
  • 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]); 
    }
  • 相关阅读:
    进制详解:二进制、八进制和十六进制
    学编程难吗?多久能入门?
    英语和数学不好,能学编程吗?
    C语言是菜鸟和大神的分水岭
    C语言究竟是一门怎样的语言?
    通俗地理解什么是编程语言
    哪款C语言编译器(IDE)适合初学者?
    spring task
    spring静态工厂方法得到单例bean
    多个切面表达式
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8439734.html
Copyright © 2011-2022 走看看