zoukankan      html  css  js  c++  java
  • bzoj3600: 没有人的算术

    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
    ",ml);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    文件操作fopen
    随机数应用
    随机数
    通过命令行参数打开文件
    命令行参数
    内存分区
    const修饰指针+volatile +restrict
    类型限定词——const
    (app笔记)Appium如何开启、配置、启用
    (app笔记)Memory Fill内存填充
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7840501.html
Copyright © 2011-2022 走看看