zoukankan      html  css  js  c++  java
  • bzoj4399 魔法少女LJJ

    Description

    在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了 LJJ感叹道“这里真是个迷人的绿色世界,空气清新、淡雅,到处散发着醉人的奶浆味;小猴在枝头悠来荡去,好不自在;各式各样的鲜花争相开放,各种树枝的枝头挂满沉甸甸的野果;鸟儿的歌声婉转动听,小河里飘着落下的花瓣真是人间仙境” SHY觉得LJJ还是太naive,一天,SHY带着自己心爱的图找到LJJ,对LJJ说:“既然你已经见识过动态树,动态仙人掌了,那么今天就来见识一下动态图吧” LJJ:“要支持什么操作?” SHY:“ 1.新建一个节点,权值为x。 2.连接两个节点。 3.将一个节点a所属于的联通快内权值小于x的所有节点权值变成x。 4.将一个节点a所属于的联通快内权值大于x的所有节点权值变成x。 5.询问一个节点a所属于的联通块内的第k小的权值是多少。 6.询问一个节点a所属联通快内所有节点权值之积与另一个节点b所属联通快内所有节点权值之积的大小。 7.询问a所在联通快内节点的数量

    Input

    第一行有一个正整数m,表示操作个数。 接下来m行,每行先给出1个正整数c。

    若c=1,之后一个正整数x,表示新建一个权值为x的节点,并且节点编号为n+1(当前有n个节点)。

    若c=2,之后两个正整数a,b,表示在a,b之间连接一条边。

    若c=3,之后两个正整数a,x,表示a联通快内原本权值小于x的节点全部变成x。

    若c=4,之后两个正整数a,x,表示a联通快内原本权值大于x的节点全部变成x。

    若c=5,之后两个正整数a,k,表示询问a所属于的联通块内的第k小的权值是多少。

    若c=6,之后两个正整数a,b,表示询问a所属联通快内所有节点权值之积与b所属联通快内所有节点权值之积的大小, 若a所属联通快内所有节点权值之积大于b所属联通快内所有节点权值之积,输出1,否则为0。

    若c=7,之后一个正整数a,表示询问a所在联通块大小

    HINT

    对100%的数据 0<=m<=400000,c<=7,所有出现的数均<=1000000000,所有出现的点保证存在

    对每个连通块维护一棵平衡树

    操作2启发式合并,操作3,4可以打标记,操作6用对数(可能会被卡精度但随机数据基本正确,也没有其他好的方法)

    线段树会被卡空间,随机数据总体时间也比平衡树慢,但极限数据操作1较少还是可以卡过去

    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    inline int _int(){
        int x=0,c=getchar();
        while(c>57||c<48)c=getchar();
        while(c>47&&c<58)x=x*10+c-48,c=getchar();
        return x;
    }
    const int N=400010;
    int ch[N][2],sz[N],rnd[N],val[N],col[N],ptr=0,stk[N],rt[N],stp=0;
    int vc[N];
    double lgv[N],lgs[N];
    void up(int w){
        sz[w]=1+sz[ch[w][0]]+sz[ch[w][1]];
        lgs[w]=lgv[w]+lgs[ch[w][0]]+lgs[ch[w][1]];
    }
    void dn(int w){
        if(!vc[w])return;
        if(int u=ch[w][0]){
            vc[u]=val[u]=vc[w];
            lgs[u]=(lgv[u]=lgv[w])*sz[u];
        }
        if(int u=ch[w][1]){
            vc[u]=val[u]=vc[w];
            lgs[u]=(lgv[u]=lgv[w])*sz[u];
        }
        vc[w]=0;
    }
    void dfs(int w){
        if(!w)return;
        stk[stp++]=w;
        dn(w);
        dfs(ch[w][0]);
        dfs(ch[w][1]);
    }
    void rot(int&w,int d){
        int u=ch[w][d];
        ch[w][d]=ch[u][d^1];
        ch[u][d^1]=w;
        up(w);
        up(w=u);
    }
    void ins(int&w,int v){
        if(w){
            ++sz[w];lgs[w]+=lgv[v];
            dn(w);
            int d=(val[w]<val[v]);
            int&u=ch[w][d];
            ins(u,v);
            if(rnd[u]>rnd[w])rot(w,d);
        }else w=v;
    }
    int kmin(int w,int k){
        --k;
        while(1){
            dn(w);
            int s=sz[ch[w][0]];
            if(s>k)w=ch[w][0];
            else if(s<k)k-=s+1,w=ch[w][1];
            else return val[w];
        }
    }
    void setmin(int w,int x){
        if(!w)return;
        dn(w);
        if(val[w]<=x){
            val[w]=x;
            lgv[w]=log(x);
            if(int u=ch[w][0]){
                vc[u]=val[u]=x;
                lgs[u]=(lgv[u]=log(x))*sz[u];
            }
            setmin(ch[w][1],x);
        }else setmin(ch[w][0],x);
        up(w);
    }
    void setmax(int w,int x){
        if(!w)return;
        dn(w);
        if(val[w]>=x){
            val[w]=x;
            lgv[w]=log(x);
            if(int u=ch[w][1]){
                vc[u]=val[u]=x;
                lgs[u]=(lgv[u]=log(x))*sz[u];
            }
            setmax(ch[w][0],x);
        }else setmax(ch[w][1],x);
        up(w);
    }
    int main(){
        srand(1844677);
        lgs[0]=0;
        for(int q=_int();q;q--)
        switch(_int()){
            case 1:{
                val[++ptr]=_int();
                rt[ptr]=col[ptr]=ptr;
                sz[ptr]=1;
                lgs[ptr]=lgv[ptr]=log(val[ptr]);
                rnd[ptr]=rand();
                break;
            }
            case 2:{
                int a=col[_int()],b=col[_int()];
                if(a!=b){
                    if(sz[rt[a]]<sz[rt[b]])a^=b,b^=a,a^=b;
                    stp=0;
                    dfs(rt[b]);
                    for(int i=0;i<stp;i++){
                        int w=stk[i];
                        lgs[w]=lgv[w];
                        col[w]=a;
                        sz[w]=1;ch[w][0]=ch[w][1]=0;
                        ins(rt[a],w);
                    }
                }
                break;
            }
            case 3:{
                int a=col[_int()],x=_int();
                setmin(rt[a],x);
                break;
            }
            case 4:{
                int a=col[_int()],x=_int();
                setmax(rt[a],x);
                break;
            }
            case 5:{
                int a=col[_int()];
                printf("%d
    ",kmin(rt[a],_int()));
                break;
            }
            case 6:{
                int a=rt[col[_int()]],b=rt[col[_int()]];
                printf("%d
    ",lgs[a]>lgs[b]);
                break;
            }
            case 7:{
                printf("%d
    ",sz[rt[col[_int()]]]);
                break;
            }
        }
        return 0;
    }
  • 相关阅读:
    初始化Winsock库
    memset与初始化
    老板不在,嚣张的正则
    教研室的下午,取快递的一天
    教研室的夜晚
    真不知道起什么名字了
    任性就是没长大咯
    难得起得早,难得周六上班
    工欲学其语,必先装软件
    151008-JS初级完成,PHP入门(变量常量等)-没假放了
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5571119.html
Copyright © 2011-2022 走看看