记录编号 439003 评测结果 AAAAAAAAAA
题目名称 [TYVJ1730]二逼平衡树 最终得分 100
用户昵称 GravatarLuciFer_T-J 是否通过 通过
代码语言 C++ 运行时间 4.158 s
提交时间 2017-08-18 16:14:36 内存使用 38.69 MiB
显示代码纯文本
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;
#define Key_value ch[ch[root][1]][0]

const int maxn=5e4+50;
const int maxm=maxn*25;
const int INF=0x3f3f3f3f;
int a[maxn];
int root[maxm],ch[maxm][2],pre[maxm],dat[maxm],num[maxm],siz[maxm];
int n,m;
int tot1,tot2,s[maxm];

void push_down(int r){

}

void push_up(int r){
    siz[r]=siz[ch[r][0]]+siz[ch[r][1]]+num[r];
}

//0 left  1 right
void Rotate(int x,int kind){
    int y=pre[x];
    push_down(y);
    push_down(x);
    ch[y][!kind]=ch[x][kind];
    pre[ch[x][kind]]=y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];
    ch[x][kind]=y;
    pre[y]=x;
    push_up(y);
    push_up(x);//模版中没有
}

void Splay(int r,int goal){
    //    push_down(r);
    while (pre[r]!=goal){
        if (pre[pre[r]]==goal){
            //            push_down(pre[r]);
            //            push_down(r);
            Rotate(r,ch[pre[r]][0]==r);
        }
        else {
            //            push_down(pre[pre[r]]);
            //            push_down(pre[r]);
            //            push_down(r);
            int y=pre[r];
            int kind=ch[pre[y]][0]==y;
            if (ch[y][kind]==r){
                Rotate(r,!kind);
                Rotate(r,kind);
            }
            else{
                Rotate(y,kind);
                Rotate(r,kind);
            }
        }
    }
    //    push_up(r);
    // if (goal==0) root=r;
}


int Find(int r,int x){
    while (r){
        if (dat[r]==x) return r;
        if (x<dat[r]){
            if (!ch[r][0]) return r;
            else r=ch[r][0];
        }
        else if (x>dat[r]){
            if (!ch[r][1]) return r;
            else r=ch[r][1];
        }
    }
    return 0;
}


void NewNode(int &r,int fa,int x){
    if (tot2) r=s[tot2--];
    else r=++tot1;
    pre[r]=fa;
    dat[r]=x;
    num[r]=1;
    siz[r]=1;
    ch[r][0]=ch[r][1]=0;
}

void Insert(int &r,int x){
    if (!r){
        NewNode(r,0,x);
        return ;
    }
    int k=Find(r,x);
  //  Splay(k,0);
  //  r=k;
    int kk=0;
    if (dat[k]==x){
        num[k]++;
        kk=k;
    }
    else if (x<dat[k]){
        NewNode(ch[k][0],k,x);
        kk=ch[k][0];
    }
    else {
        NewNode(ch[k][1],k,x);
        kk=ch[k][1];
    }
    while (k){
        siz[k]++;
        k=pre[k];
    }
    Splay(kk,0);
    r=kk;
}

void Delete(int &r,int x){
    int k=Find(r,x);
    Splay(k,0);
    r=k;
    if (num[k]>1){
        num[k]--;
        siz[k]--;
        return ;
    }
    else{
        if (!ch[r][0]){
            s[++tot2]=r;
            r=ch[r][1];
            pre[r]=0;
            return ;
        }
        else if (!ch[r][1]){
            s[++tot2]=r;
            r=ch[r][0];
            pre[r]=0;
            return ;
        }
        else{
            pre[ch[r][0]]=0;
            int p=Find(ch[r][0],INF);
            Splay(p,0);
            ch[p][1]=ch[r][1];
            pre[ch[r][1]]=p;
            s[++tot2]=r;
            r=p;
            pre[r]=0;
        }
    }
}

void Build(int p,int l,int r){
    for (int i=l;i<=r;i++) Insert(root[p],a[i]);
    if (l==r) return ;
    int mid=(l+r)>>1;
    Build(p*2,l,mid);
    Build(p*2+1,mid+1,r);
}

void Init(){
    memset(root,0,sizeof(root));
    tot1=tot2=0;
    pre[0]=num[0]=dat[0]=ch[0][0]=ch[0][1]=0;
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    Build(1,1,n);
}

int Ask_rank(int &r,int x){
    int k=Find(r,x);
    Splay(k,0);
    r=k;
    if (dat[k]>=x) return siz[ch[k][0]];
    else return siz[ch[k][0]]+num[k];
}

int Ask_rank(int p,int l,int r,int L,int R,int x){
    if (L<=l && r<=R){
        return Ask_rank(root[p],x);
    }
    int mid=(l+r)>>1;
    int tmp=0;
    if (L<=mid) tmp+=Ask_rank(p*2,l,mid,L,R,x);
    if (R>mid) tmp+=Ask_rank(p*2+1,mid+1,r,L,R,x);
    return tmp;
}

void Change_add(int p,int l,int r,int x,int y){
    Insert(root[p],y);
    if (l==r) return ;
    int mid=(l+r)>>1;
    if (x<=mid) Change_add(p*2,l,mid,x,y);
    else Change_add(p*2+1,mid+1,r,x,y);
}

void Change_del(int p,int l,int r,int x,int y){
    Delete(root[p],y);
    if (l==r) return ;
    int mid=(l+r)>>1;
    if (x<=mid) Change_del(p*2,l,mid,x,y);
    else Change_del(p*2+1,mid+1,r,x,y);
}

int Ask_pre(int &r,int x){
    int k=Find(r,x);
    Splay(k,0);
    r=k;
    if (dat[k]>=x) {
        if (!ch[k][0]) return -INF;
        int p=Find(ch[k][0],INF);
        Splay(p,0);
        r=p;
        return dat[p];
    }
    else return dat[k];
}


int Ask_pre(int p,int l,int r,int L,int R,int x){
    if (L<=l && r<=R) return Ask_pre(root[p],x);
    int mid=(l+r)>>1;
    int tmp=-INF;
    if (L<=mid) tmp=max(tmp,Ask_pre(p*2,l,mid,L,R,x));
    if (R>mid) tmp=max(tmp,Ask_pre(p*2+1,mid+1,r,L,R,x));
    return tmp;
}

int Ask_succ(int &r,int x){
    int k=Find(r,x);
    Splay(k,0);
    r=k;
    if (dat[k]<=x) {
        if (!ch[k][1]) return INF;
        int p=Find(ch[k][1],-INF);
        Splay(p,0);
        r=p;
        return dat[p];
    }
    else return dat[k];
}

int Ask_succ(int p,int l,int r,int L,int R,int x){
    if (L<=l && r<=R) return Ask_succ(root[p],x);
    int mid=(l+r)>>1;
    int tmp=INF;
    if (L<=mid) tmp=min(tmp,Ask_succ(p*2,l,mid,L,R,x));
    if (R>mid) tmp=min(tmp,Ask_succ(p*2+1,mid+1,r,L,R,x));
    return tmp;
}

int Work(int ll,int rr,int k){
    int l=0,r=1e8;
    while (l<r){
        int mid=(l+r)>>1;
        if (Ask_rank(1,1,n,ll,rr,mid)>=k) r=mid;
        else l=mid+1;
    }
    return l-1;
}

int main(){
    freopen("psh.in","r",stdin);
    freopen("psh.out","w",stdout);
    scanf("%d%d",&n,&m);
    Init();
    // debug();
    while (m--){
        int op;
        int l,r,k;
        scanf("%d",&op);
        if (op==1){
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",Ask_rank(1,1,n,l,r,k)+1);
        }
        else if (op==2){
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",Work(l,r,k));
        }
        else if (op==3){
            scanf("%d%d",&l,&k);
            Change_del(1,1,n,l,a[l]);
            a[l]=k;
            Change_add(1,1,n,l,a[l]);
        }
        else if (op==4){
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",Ask_pre(1,1,n,l,r,k));
        }
        else if (op==5){
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",Ask_succ(1,1,n,l,r,k));
            //          debug();
        }
    }
    return 0;
}