zoukankan      html  css  js  c++  java
  • BZOJ 4777 Usaco2017 Open Switch Grass Kruskal+替罪羊树+权值线段树

    这道题首先可以看出答案一定是一条边,而且答案一定在最小生成树上,那么我们就可以在这个最小生成树上维护他与异色儿子的边最小值,所以我们就可以已通过Kruskal和一棵平衡树来解决,时间复杂度是O(n*logn)级别的但是那个大常数..........然后在最外面独立一棵权值线段树来存最终答案.....

    证明:若答案不是一条边,那么在这个答案里一定有中间点可以推翻答案;若答案不是在最小生成树内,那么在最小生成树上一定用答案可以更新他(这个答案边与最小生成树内这两个点的路径形成回路,那么他一定会被推翻)(最小生成树外的边与最小生成树形成回路,那个路径一定比回路内其它边大(或等),会被其它边替代)

    一定要注意当查询时替罪羊的中间点可以生效时当且仅当,他在区间内并且他存在。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #define MAXN 200005
    #define Inf 1000000
    using namespace std;
    double alpha=0.756;
    inline int read()
    {
        int sum=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')
        {
            sum=(sum<<1)+(sum<<3)+ch-48;
            ch=getchar();
        }
        return sum;
    }
    int sz;
    struct Seg_Tree
    {
        Seg_Tree *ch[2];
        int l,r,mid,size;
    }node[Inf<<2],*seg;
    inline Seg_Tree *New(int l,int r)
    {
        Seg_Tree *p=&node[++sz];
        p->l=l;
        p->r=r;
        p->mid=(l+r)>>1;
        p->size=0;
        return p;
    }
    inline int Min(int x,int y)
    {
        return x<y?x:y;
    }
    struct ScapeGoat_Tree
    {
        ScapeGoat_Tree *ch[2],*f;
        int key,size,col,ex,cover,min;
        void pushup()
        {
            size=ch[1]->size+ex+ch[0]->size;
            cover=ch[1]->cover+1+ch[0]->cover;
            min=Min(ch[0]->min,ch[1]->min);
            if(ex)min=Min(key,min);
        }
        bool bad()
        {
            return cover*alpha+5<ch[1]->cover||cover*alpha+5<ch[0]->size;
        }
    }mempool[MAXN<<1],*list[MAXN<<1],*stack[MAXN<<1],*null,*root[MAXN],*pos[MAXN];
    int len,top;
    inline void pre()
    {
       null=mempool;
       for(int i=1;i<(MAXN<<1);i++)stack[++top]=mempool+i;
       null->ch[0]=null->ch[1]=null->f=null;
       null->key=null->min=0x7fffffff;
       for(int i=1;i<MAXN;i++)root[i]=null;
    }
    inline ScapeGoat_Tree *New(int key,ScapeGoat_Tree *fa,int co)
    {
        ScapeGoat_Tree *p=stack[top--];
        p->ch[1]=p->ch[0]=null;
        p->min=p->key=key;
        p->f=fa;
        p->col=co;
        p->size=p->cover=p->ex=1;
        return p;
    }
    struct Tr
    {
        int to,next,w;
    }C[MAXN<<1];
    int Head[MAXN],T;
    inline void Add(int x,int y,int z)
    {
        C[++T].to=y;
        C[T].next=Head[x];
        Head[x]=T;
        C[T].w=z;
    }
    int col[MAXN],Ans[MAXN];
    struct E
    {
        int x,y,z;
    }e[MAXN];
    int n,m,k,q;
    int Fa[MAXN];
    int comp(const E a,const E b)
    {
        return a.z<b.z;
    }
    int f[MAXN];
    int find(int x)
    {
        return Fa[x]==x?x:(Fa[x]=find(Fa[x]));
    }
    inline void unit(int x,int y)
    {
        if(x!=y)Fa[x]=y;
    }
    inline void Kruskal()
    {
       sort(e+1,e+m+1,comp);
       for(int i=1;i<=n;i++)
        Fa[i]=i;
       int had=0;
       for(int i=1;i<=m;i++)
        if(find(e[i].x)!=find(e[i].y))
        {
            Add(e[i].x,e[i].y,e[i].z);
            Add(e[i].y,e[i].x,e[i].z);
            unit(find(e[i].x),find(e[i].y));
            had++;
            if(had==n)break;
        }
    }
    ScapeGoat_Tree **insert(int key,int co,ScapeGoat_Tree *&p,int id,ScapeGoat_Tree *fa)
    {
        if(p==null)
        {
            p=New(key,fa,co);
            pos[id]=p;
            return &null;
        }
        ScapeGoat_Tree **ret=insert(key,co,p->ch[p->col<=co],id,p);
        if(p->bad())ret=&p;
        p->pushup();
        return ret;
    }
    void travel(ScapeGoat_Tree *p)
    {
        if(p==null)return;
        travel(p->ch[0]);
        if(p->ex)list[++len]=p;
        else stack[++top]=p;
        travel(p->ch[1]);
    }
    ScapeGoat_Tree *divide(int l,int r,ScapeGoat_Tree *fa)
    {
        if(l>r)return null;
        int mid=(l+r)>>1;
        list[mid]->ch[0]=divide(l,mid-1,list[mid]);
        list[mid]->ch[1]=divide(mid+1,r,list[mid]);
        list[mid]->f=fa;
        list[mid]->pushup();
        return list[mid];
    }
    inline void rebuild(ScapeGoat_Tree *&p)
    {
        len=0;
        ScapeGoat_Tree *fa=p->f;
        travel(p);
        p=divide(1,len,fa);
    }
    inline void Insert(int key,int co,ScapeGoat_Tree *&Root,int id)
    {
        ScapeGoat_Tree **p=insert(key,co,Root,id,null);
        if(*p!=null)rebuild(*p);
    }
    void dfs(int x)
    {
        for(int i=Head[x];i;i=C[i].next)
        if(C[i].to!=f[x])
        {
          f[C[i].to]=x;
          Insert(C[i].w,col[C[i].to],root[x],C[i].to);
          dfs(C[i].to);
        }
    }
    void build(Seg_Tree *p)
    {
        if(p->l==p->r)return;
        p->ch[0]=New(p->l,p->mid);
        p->ch[1]=New(p->mid+1,p->r);
        build(p->ch[0]);
        build(p->ch[1]);
    }
    inline int Rank(int co,ScapeGoat_Tree *Root)
    {
        ScapeGoat_Tree *p=Root;
        int ret=0;
        while(p!=null)
         if(p->col>=co)
          p=p->ch[0];
         else
          ret+=p->ch[0]->size+p->ex,p=p->ch[1];
        return ret;
    }
    int query(ScapeGoat_Tree *p,int l,int r)
    {
        if(l>r)return 0x7fffffff;
        if(p==null)return 0x7fffffff;
        if(l<=1&&r>=p->size)
         return p->min;
        int ans=0x7fffffff;
        if(p->ex&&l<=p->ch[0]->size+p->ex&&r>=p->ch[0]->size+p->ex)
         ans=p->key;
        if(l<=p->ch[0]->size)
         ans=Min(ans,query(p->ch[0],l,r));
        if(r>p->ch[0]->size+p->ex)
         ans=Min(ans,query(p->ch[1],l-(p->ch[0]->size+p->ex),r-(p->ch[0]->size+p->ex)));
        return ans;
    }
    inline int Query(int x)
    {
        int l=Rank(col[x],root[x]);
        int ans=query(root[x],1,l);
        int r=Rank(col[x]+1,root[x])+1;
        ans=Min(ans,query(root[x],r,root[x]->size));
        return ans;
    }
    void update(Seg_Tree *p,int key)
    {
        if(key>Inf)return;
        p->size++;
        if(p->l==p->r)return;
        update(p->ch[p->mid<key],key);
    }
    inline void Init()
    {
        n=read(),m=read(),k=read(),q=read();
        for(int i=1;i<=m;i++)
            e[i].x=read(),e[i].y=read(),e[i].z=read();
        Kruskal();
        for(int i=1;i<=n;i++)col[i]=read();
        dfs(1);
        seg=New(1,Inf);
        build(seg);
        for(int i=1;i<=n;i++)
         update(seg,(Ans[i]=Query(i)));
    }
    inline void Del(int x)
    {
        pos[x]->ex=0;
        ScapeGoat_Tree *p=pos[x];
        while(p!=null)
         p->pushup(),p=p->f;
    }
    void del(Seg_Tree *p,int key)
    {
        if(key>Inf)return;
        p->size--;
        if(p->l==p->r)return;
        del(p->ch[p->mid<key],key);
    }
    int get_ans(Seg_Tree *p)
    {
        if(p->l==p->r)return p->mid;
        if(p->ch[0]->size)return get_ans(p->ch[0]);
        else return get_ans(p->ch[1]);
    }
    inline void work()
    {
      while(q--)
      {
         int x=read(),y=read();
         if(x!=1)Del(x);
         if(x!=1)if(root[f[x]]->bad())rebuild(root[f[x]]);
         col[x]=y;
         if(x!=1)Insert(pos[x]->key,y,root[f[x]],x);
         del(seg,Ans[x]);
         if(x!=1)del(seg,Ans[f[x]]);
         update(seg,(Ans[x]=Query(x)));
         if(x!=1)update(seg,(Ans[f[x]]=Query(f[x])));
         printf("%d
    ",get_ans(seg));
      }
    }
    int main()
    {
      pre();
      Init();
      work();
      return 0;
    }
  • 相关阅读:
    自主开发与带兵打仗
    外包项目的内外部管理
    服务器运维工程师岗位要求
    “互联网+”下, 经销商价值再思考
    外包软件项目管理要抓住关键点
    软件外包项目管理的经验感悟
    关于软件外包项目管理的想法
    九型人格判定
    好的学习材料
    前端学习的好去处
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7152806.html
Copyright © 2011-2022 走看看