ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

http://www.lydsy.com/JudgeOnline/problem.php?id=3600

题意大概是维护一个由二叉树组成的序列a,初始每个位置为单个点的树,支持单点修改(把a[l]和a[r]分别作为根的左右子树,放在a[x]),查询区间最大值(按先序遍历字典序比较,空<非空)的位置。

用动态标号法维护一下当前已出现过的所有二叉树的大小顺序,线段树支持区间查询。

#include<bits/stdc++.h>
typedef long long i64;
const int P=1844677,MX=1<<30;
char ib[10000007],*ip=ib;
int _(){
    int x=0;
    while(*ip<48)++ip;
    while(*ip>47)x=x*10+*ip++-48;
    return x;
}
int n,m,tr[277777],a[133333],mx,idp=0;
struct node{
    node*c[2];
    int rnd,M,ls,rs;
    void rb(int L,int R){
        if(!this)return;
        M=L+R;
        c[0]->rb(L,M>>1);
        c[1]->rb(M>>1,R);
    }
}ns[500007],*np=ns,*rt;
bool cmp(int a,int b){return ns[a].M<ns[b].M;}
void up(int&w,int l,int r){w=cmp(a[l],a[r])?r:l;}
bool cmp(node*a,node*b){return a==ns||(a->ls!=b->ls?cmp(a->ls,b->ls):cmp(a->rs,b->rs));}
int h[P][4];
#define $(a,b,c) (*a=b,a=&c,b=*a)
void ins(int x,int ls,int rs){
    node**w=&rt;
    *np=(node){0,0,rand(),0,ls,rs};
    int L=0,R=MX;
    for(;;){
        node*a=*w;
        if(!a||np->rnd>a->rnd){
            *w=np;
            np->M=L+R;
            node**l=np->c,**r=l+1;
            while(a)cmp(a,np)?$(l,a,a->c[1]):$(r,a,a->c[0]);
            *l=*r=0;
            return np++->rb(L,R);
        }
        int d=cmp(a,np);
        w=a->c+d;
        (d?L:R)=(L+R)>>1;
    }
}
int getid(int a,int b){
    int w=(a*149+b*293)%P;
    while(h[w][0]){
        if(h[w][1]==a&&h[w][2]==b)return h[w][3];
        w=(w+13999)%P;
    }
    h[w][0]=1;
    h[w][1]=a;
    h[w][2]=b;
    h[w][3]=++idp;
    ins(idp,a,b);
    return idp;
}
int main(){
    fread(ib,1,sizeof(ib),stdin);
    n=_();m=_();
    srand(n+m+131);
    for(mx=2;mx<=n+2;mx<<=1);
    for(int i=1;i<=n;++i)tr[mx+i]=i;
    for(int i=mx-1;i;--i)tr[i]=tr[i*2];
    ins(0,-1,-1);
    while(m--){
        int o=_(),l=_(),r=_();
        if(o+48=='C'){
            int x=_();
            a[x]=getid(a[l],a[r]);
            for(int w=mx+x>>1;w;w>>=1)up(tr[w],tr[w*2],tr[w*2+1]);
        }else{
            int ml=l,mr=r;
            for(l+=mx,r+=mx;r-l>1;l>>=1,r>>=1){
                if(~l&1)up(ml,ml,tr[l+1]);
                if(r&1)up(mr,tr[r-1],mr);
            }
            up(ml,ml,mr);
            printf("%d\n",ml);
        }
    }
    return 0;
}
View Code

 

posted on 2017-11-15 19:09  nul  阅读(312)  评论(0编辑  收藏  举报