bzoj4399 魔法少女LJJ

Posted ccz181078

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",kmin(rt[a],_int()));
            break;
        }
        case 6:{
            int a=rt[col[_int()]],b=rt[col[_int()]];
            printf("%d\n",lgs[a]>lgs[b]);
            break;
        }
        case 7:{
            printf("%d\n",sz[rt[col[_int()]]]);
            break;
        }
    }
    return 0;
}

 

以上是关于bzoj4399 魔法少女LJJ的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4399 魔法少女LJJ

AC日记——魔法少女LJJ bzoj 4399

题解:BZOJ4399(魔法少女LJJ)

[BZOJ4399]魔法少女LJJ

[BZOJ4399]魔法少女LJJ----------线段树进阶

[BZOJ4399]魔法少女LJJ