【bzoj3600】没有人的算术

因为阿咸,所以不会写题解。

大概就是平衡树维护大小关系然后随意线段树就好。

每次更新一下线段树上的区间max

#include<bits/stdc++.h>
#define ll long long
#define alpha 0.7
#define maxn 500005
#define INF 1ll<<60

using namespace std;

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

ll tag[maxn];

struct node{
    int first,second;
    node(int first,int second):first(first),second(second){};
    node(){};
    friend bool operator == (node A,node B){
        return (A.first==B.first)&&(A.second==B.second);
    }
    friend bool operator < (node A,node B){
        if(tag[A.first]==tag[B.first])return tag[A.second]<tag[B.second];
        return tag[A.first]<tag[B.first];
    }
};

int n,m,tmp,root,pos[maxn];

struct sctree{
    int top,cnt,size[maxn],id[maxn],ch[maxn][2];
    node val[maxn];
    inline void pushup(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}
    inline void build(int &x,int l,int r,ll lv,ll rv){
        if(l>r){x=0;return;}
        if(l==r){
            x=id[l];size[x]=1;
            tag[x]=lv+rv>>1;
            ch[x][0]=ch[x][1]=0;
            return;
        }
        int mid=l+r>>1;
        x=id[mid];tag[x]=lv+rv>>1;
        build(ch[x][0],l,mid-1,lv,tag[x]-1);
        build(ch[x][1],mid+1,r,tag[x]+1,rv);
        pushup(x);
    }
    inline void dfs(int x){
        if(!x)return;
        dfs(ch[x][0]);
        id[++top]=x;
        dfs(ch[x][1]);
    }
    inline void rebuild(int &x,ll lv,ll rv){
        top=0;
        dfs(x);
        build(x,1,top,lv,rv);
    }
    inline int insert(int &x,ll lv,ll rv,node v){
        if(!x){
            x=++cnt;size[x]=1;
            tag[x]=lv+rv>>1;
            val[x]=v;
            return x;
        }
        if(val[x]==v)return x;
        int p;
        ll mid=lv+rv>>1;
        if(v<val[x])p=insert(ch[x][0],lv,mid-1,v);
        else p=insert(ch[x][1],mid+1,rv,v);
        pushup(x);
        if(1.0*size[x]*alpha>1.0*max(size[ch[x][0]],size[ch[x][1]])){
            if(tmp){
                if(ch[x][0]==tmp)rebuild(ch[x][0],lv,mid-1);
                else rebuild(ch[x][1],mid+1,rv);
                tmp=0;
            }
        }else tmp=x;
        return p;
    }
}T1;

int Max;

struct Segment_Tree{
    int mx[maxn];
    inline void pushup(int o){
        int ls=mx[o<<1],rs=mx[o<<1|1];
        if(tag[pos[ls]]<tag[pos[rs]])mx[o]=rs;else mx[o]=ls;
    }
    inline void build(int o,int l,int r){
        if(l==r){
            mx[o]=l;
            return;
        }
        int mid=l+r>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
        pushup(o);
    }
    inline void change(int o,int l,int r,int x){
        if(l==r){
            mx[o]=l;
            return;
        }
        int mid=l+r>>1;
        if(x<=mid)change(o<<1,l,mid,x);
        else change(o<<1|1,mid+1,r,x);
        pushup(o);
    }
    inline void query(int o,int l,int r,int x,int y){
        if(x<=l&&r<=y){
            if(tag[pos[Max]]<tag[pos[mx[o]]])Max=mx[o];
            return;
        }
        int mid=l+r>>1;
        if(y<=mid)query(o<<1,l,mid,x,y);
        else if(x>mid)query(o<<1|1,mid+1,r,x,y);
        else {
            query(o<<1,l,mid,x,mid);
            query(o<<1|1,mid+1,r,mid+1,y);
        }
    }
}T2;

char ch[2];

int main(){
    n=read();m=read();tag[0]=-1;
    T1.insert(root,0,INF,node(0,0));
    for(int i=1;i<=n;++i)pos[i]=1;
    T2.build(1,1,n);
    int f1,f2,f3;
    for(int i=1;i<=m;++i){
        scanf("%s",ch);f1=read();f2=read();
        if(ch[0]=='C'){
            f3=read();
            pos[f3]=T1.insert(root,0,INF,node(pos[f1],pos[f2]));
            if(tmp){T1.rebuild(root,0,INF);tmp=0;}
            T2.change(1,1,n,f3);
        }else{
            Max=0;
            T2.query(1,1,n,f1,f2);
            printf("%d\n",Max);
        }
    }
    return 0;
}

 

posted @ 2017-09-18 21:18  Illya  阅读(317)  评论(1编辑  收藏  举报