zoukankan      html  css  js  c++  java
  • Luogu_4197 Peaks

    P4197 Peaks

    并不会克鲁斯卡尔重构树,于是就写了离线算法。

    使用了最小生成树,启发式合并treap

    在最小生成树,克鲁斯卡尔算法 时 ,将询问一块处理。便可以保证询问时边的要求。然后利用平衡树,加速计算。

    // luogu-judger-enable-o2
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <ctime>
    
    #define Ls T[R].ch[0]
    #define Rs T[R].ch[1]
    #define T_d T[R].ch[d]
    
    using std::sort;
    
    const int maxn=201000;
    const int inf=0x7fffffff;
    
    struct Tree
    {
        int val;
        int key;
        int Size;
        int Self;
        int ch[2];
        Tree(int a=0,int b=1,int c=1)
        {
            key=rand();
            val=a;
            Size=b;
            Self=c;
            ch[0]=ch[1]=0;
        }
        void Clear()
        {
            Size=Self;
            ch[0]=ch[1]=0;
        }
    };
    
    struct Data
    {
        int A,B;
        int Value,Tag;
        int Num;
        Data (int a=0,int b=0,int v=0,int t=-inf,int n=0)
        {
            A=a;B=b;
            Value=v;
            Tag=t;
            Num=n;
        }
    };
    
    Tree T[maxn];
    Data base[maxn*5];
    int h[maxn],f[maxn],tail;
    int belong[maxn],ans[maxn*5];
    
    int Find(int x)
    {
        if(f[x]==x) return f[x];
        return f[x]=Find(f[x]);
    }
    
    int compare(const Data &a,const Data &b)
    {
        if(a.Value!=b.Value)    return a.Value<b.Value;
        return a.Tag<b.Tag;
    }
    
    int cmpkth(int R,int kth)
    {
        int s=T[Rs].Size;
        if(kth<=s)  return 1;
        if(kth>s+T[R].Self) return 0;
        return -1;
    }
    
    int cmpval(int R,int val)
    {
        if(T[R].val==val)   return -1;
        return T[R].val<val;
    }
    
    void  Sum(int R)
    {
        T[R].Size=T[R].Self+T[Ls].Size+T[Rs].Size;
        return ;
    }
    
    void Rotate(int &R,int dir)
    {
        int k=T[R].ch[dir^1];
        T[R].ch[dir^1]=T[k].ch[dir];
        T[k].ch[dir]=R;
        Sum(R);Sum(k);
        R=k;
    }
    
    int Seek_kth(int R,int kth)
    {
        int d=cmpkth(R,kth);
        if(d==-1)   return T[R].val;
        return Seek_kth(T_d,kth-=( d==0 ? T[Rs].Size+T[R].Self : 0 ));
    }
    
    void Insert(int &R,int val,int model=0,int num=0)
    {
        if(R==0)
        {
            if(model==0){   R=++tail;T[R]=Tree(val); }
            else    {   T[num].Clear();R=num; }
            return ;
        }
        int d=cmpval(R,val);
        if(d==-1)
        {
            int add=( model ? T[num].Self : 1 );
            T[R].Self+=add;
            T[R].Size+=add;
            return ;
        }
        Insert(T_d,val,model,num);
        Sum(R);
        if(T[T_d].key>T[R].key) Rotate(R,d^1);
        return ;
    }
    
    void _merge(int &R,int &Dir)
    {
        if(R==0)    return ;
        _merge(Ls,Dir);
        _merge(Rs,Dir);
        Insert(Dir,T[R].val,1,R);
        return ;
    }
    
    void Merge(int &A,int &B,int f1,int f2)
    {
        if(T[A].Size>T[B].Size)
        {
            _merge(B,A);
            f[f2]=f1;
            B=A;
            return ;
        }
        else
        {
            _merge(A,B);
            f[f1]=f2;
            A=B;
            return ;
        }
    }
    
    void visit(int now)
    {
        if(now==0)  return ;
        visit(T[now].ch[0]);
        printf("%d ",T[now].val);
        visit(T[now].ch[1]);
    }
    
    int main()
    {
        srand(time(NULL));
        int n,m,q;
        T[0].Self=0;T[0].Size=0;
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=n;i++)
            scanf("%d",&h[i]),f[i]=i;
        for(int i=1;i<=n;i++)
            Insert(belong[i],h[i]);
        for(int i=1;i<=m;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            base[i]=Data(a,b,c);
        }
        for(int i=1;i<=q;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            base[i+m]=Data(a,c,b,0,i);
            ans[i]=-1;
        }
        sort(base+1,base+1+m+q,compare);
        for(int i=1;i<=m+q;i++)
        {
            if(base[i].Tag==0)
            {
                int _f=Find(base[i].A);
                if(T[belong[_f]].Size>=base[i].B)
                    ans[base[i].Num]=Seek_kth(belong[_f],base[i].B);
            }
            else
            {
                int f1=Find(base[i].A),f2=Find(base[i].B);
                if(f1==f2)  continue;
                Merge(belong[f1],belong[f2],f1,f2);
            }
        }
        for(int i=1;i<=q;i++)
            printf("%d
    ",ans[i]);
    //    return 0;
        return 0;
    }
    
    
  • 相关阅读:
    搜索框
    鼠标hover时改变图片透明度和颜色(方法二)
    让背景带上颜色
    右侧固定导航栏
    react native环境配置
    左侧固定导航栏
    鼠标hover时改变图片透明度和颜色
    androidSDK配置环境变量
    cordova插件开发
    Python电子书分享
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/10332314.html
Copyright © 2011-2022 走看看