zoukankan      html  css  js  c++  java
  • BZOJ 4129 Haruna’s Breakfast 树上莫队

    树上莫队求mex,关键点:I.树上莫队(废话)II.树状数组+二分 log^2 求mex 

    树上莫队的时间复杂度一定是O(n1.5)的证明 I.右端点dfs序 II.左端点均摊(卡的话是一个近似二次函数的东西,会随着卡你的地方增多而卡的程度减小)

    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #define N 18
    #define MAXN 51000
    using namespace std;
    int pos[MAXN+10],id[MAXN+10],a[MAXN+10],b[MAXN+10],len,n,m,f[MAXN+10][N+10],size,d[MAXN+10],had[MAXN+10];
    bool belong[MAXN+10];
    struct Q
    {
       int l,r,time,ans,id;
    }q[MAXN+10];
    struct T
    {
       int a,b,pos;
    }t[MAXN+10];
    struct Tree
    {
       int to,next; 
    }c[MAXN<<2];
    int head[MAXN+10],sz,cause;
    inline void update(int x,int i)
    {
       if(x==0)return;
       while(x<MAXN)
       {
          b[x]+=i;
          x+=x&(-x);
       }
    }
    inline int sum(int x)
    {
       int ret=0;
       while(x>0)
       {
         ret+=b[x];
         x-=x&(-x);
       }
       return ret;
    }
    inline void add(int x,int y)
    {
       c[++sz].to=y;
       c[sz].next=head[x];
       head[x]=sz;
       c[++sz].to=x;
       c[sz].next=head[y];
       head[y]=sz;
    }
    int l,r,now;
    void dfs(int x)
    {
       id[x]=++cause;
       d[x]=d[f[x][0]]+1;
       for(int i=1;i<N;i++)
        f[x][i]=f[f[x][i-1]][i-1];
       for(int i=head[x];i;i=c[i].next)
       if(c[i].to!=f[x][0])
       {
         f[c[i].to][0]=x;
         dfs(c[i].to);
       }
    }
    int comp(const Q aa,const Q bb)
    {
       return pos[id[aa.l]]<pos[id[bb.l]]||(pos[id[aa.l]]==pos[id[bb.l]]&&id[aa.r]<id[bb.r]);
    }
    int end_comp(const Q aa,const Q bb)
    {
       return aa.id<bb.id;
    }
    void pre()
    {
       scanf("%d%d",&n,&m);
       len=(int)(sqrt(n+0.5));
       for(int i=1;i<=n;i++)
       {
        scanf("%d",&a[i]);
        pos[i]=(i-1)/len+1;
       }
       for(int i=1;i<n;i++)
       {
         int x,y;
         scanf("%d%d",&x,&y);
         add(x,y);
       }
       dfs(1);
       for(int i=1;i<=m;i++)
       {
         int opt,x,y;
         scanf("%d%d%d",&opt,&x,&y);
         if(opt==0)
         {
            now++;
            t[now].a=a[x];
            t[now].b=y;
            t[now].pos=x;
            a[x]=y;
         }
         else
         {
            q[++size].l=x;
            q[size].r=y;
            q[size].time=now;
            q[size].id=size;
         }
       }
       sort(q+1,q+size+1,comp);
       l=r=1;
       belong[1]=1;
       if(a[1]<MAXN)had[a[1]]=1;
       if(a[1]>=MAXN||a[1]==0)return;
       update(a[1],1);
    }
    int Lca(int x,int y)
    {
       if(d[x]<d[y]) x^=y^=x^=y;
       int k=d[x]-d[y];
       for(int i=0;i<N;i++)
         if((1<<i)&k)
          x=f[x][i];
       if(x==y)
       {
         return x;
       }
       for(int i=N-1;i>=0;i--)
       if(f[x][i]!=f[y][i])
       {
         x=f[x][i];
         y=f[y][i];
       }
       return f[x][0];
    }
    inline void via(int x)
    {
       belong[id[x]]^=1;
       if(a[x]>=MAXN)return;
       if(belong[id[x]])
       {
         had[a[x]]++;
         if(a[x]==0)return;
         if(had[a[x]]==1)
          update(a[x],1);
       }
       else
       {
         had[a[x]]--;
         if(a[x]==0)return;
         if(had[a[x]]==0)
          update(a[x],-1);
       }
    }
    inline void come(int x)
    {
       if(!x)return;
       a[t[x].pos]=t[x].b;
       if(belong[id[t[x].pos]])
       {
         if(t[x].a<MAXN)
         {
            had[t[x].a]--;
            if(t[x].a!=0&&had[t[x].a]==0)
             update(t[x].a,-1);
         }
         if(t[x].b<MAXN)
         {
            had[t[x].b]++;
            if(t[x].b!=0&&had[t[x].b]==1)
             update(t[x].b,1);
         }
       }
    }
    inline void go(int x)
    {
       if(!x)return;
       a[t[x].pos]=t[x].a;
       if(belong[id[t[x].pos]])
       {
         if(t[x].b<MAXN)
         {
            had[t[x].b]--;
            if(t[x].b!=0&&had[t[x].b]==0)
             update(t[x].b,-1);
         }
         if(t[x].a<MAXN)
         {
            had[t[x].a]++;
            if(t[x].a!=0&&had[t[x].a]==1)
             update(t[x].a,1);
         }
       }
    }
    inline int answer()
    {
       if(had[0]==0)return 0;
       int z=1,y=MAXN-1,ans=0;
       while(z<=y)
       {
          int mid=(z+y)>>1;
          int ques=sum(mid);
          if(ques<mid)
           ans=mid,y=mid-1;
          else
           z=mid+1;
       }
       return ans;
    }
    void work()
    {
       for(int i=1;i<=size;i++)
       {
          while(now<q[i].time)come(++now);
          while(now>q[i].time)go(now--);
          int lca1=Lca(q[i].l,q[i].r);
          int lca2=Lca(l,r);
          int lca3=Lca(q[i].l,l);
          int lca4=Lca(q[i].r,r);
          while(l!=lca3)
          {
             via(l);
             l=f[l][0];
          }
          l=q[i].l;
          while(l!=lca3)
          {
             via(l);
             l=f[l][0];
          }
          l=q[i].l;
          while(r!=lca4)
          {
             via(r);
             r=f[r][0];
          }
          r=q[i].r;
          while(r!=lca4)
          {
             via(r);
             r=f[r][0];
          }
          r=q[i].r;
          if(lca1!=lca2)
          {
              via(lca1);
              via(lca2);              
          }
          q[i].ans=answer();
       }
    }
    void print()
    {
       sort(q+1,q+size+1,end_comp);
       for(int i=1;i<=size;i++)
        printf("%d
    ",q[i].ans);
    }
    int main()
    {
        pre();
        work();
        print();
        return 0;
    } 
  • 相关阅读:
    MyEclipse 2015反编译插件安装
    RocketMQ事务消费和顺序消费详解
    Rocket重试机制,消息模式,刷盘方式
    前端js上传文件 到后端接收文件
    Junit进行单元测试
    json简单使用
    valgrind的使用--检测内存
    使用scrapy框架爬取自己的博文(3)
    使用scrapy框架爬取自己的博文
    Scrapy下xpath基本的使用方法
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7072752.html
Copyright © 2011-2022 走看看