BZOJ 3196 二逼平衡树

Posted on 2017-03-08 11:11  ziliuziliu  阅读(166)  评论(0编辑  收藏  举报

为什么这么慢呢。。。。都是线段树套splay为什么就只能卡过去呢。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50050
#define maxm 4000050 
#define inf 100000001
using namespace std;
int n,m,tot1=0,tot2=0,tr_root,root[maxn<<2],ls[maxn<<2],rs[maxn<<2],tmp=0,x[maxn],mn[maxn<<2];
int tree[maxm][3],fath[maxm],size[maxm],cnt[maxm],val[maxm];
int type,l,r,pos,k;
int pre,sub,tmp1,tmp2;
void reset(int x)
{
    root[x]=++tot2;tree[root[x]][2]=++tot2;fath[tot2]=root[x];
    size[root[x]]=2;size[tot2]=1;
    val[root[x]]=-1;val[tot2]=inf;cnt[root[x]]=cnt[tot2]=1;
}
void pushup(int now) {size[now]=size[tree[now][1]]+size[tree[now][2]]+cnt[now];}
void sg_build(int &now,int left,int right)
{
    now=++tot1;reset(now);mn[now]=inf;
    if (left==right) return;
    int mid=left+right>>1;
    sg_build(ls[now],left,mid);
    sg_build(rs[now],mid+1,right);
}
void insert(int &now,int father,int k)
{
    if (!now)
    {
        now=++tot2;fath[now]=father;size[now]=cnt[now]=1;val[now]=k;
        return;
    }
    if (val[now]==k)
    {
        cnt[now]++;size[now]++;
        return;
    }
    if (k<val[now]) insert(tree[now][1],now,k);
    else insert(tree[now][2],now,k);
    pushup(now);
}
void rotate(int x,int &k)
{
    int y=fath[x],z=fath[y],l,r;
    if (tree[y][1]==x) l=1;else l=2;r=3-l;
    if (y==k) k=x;
    else
    {
        if (tree[z][1]==y) tree[z][1]=x;
        else tree[z][2]=x;
    }
    fath[x]=z;fath[y]=x;fath[tree[x][r]]=y;
    tree[y][l]=tree[x][r];tree[x][r]=y;
    pushup(y);pushup(x);
}
void splay(int x,int &k)
{
    while (x!=k)
    {
        int y=fath[x],z=fath[y];
        if (y!=k)
        {
            if ((tree[y][1]==x)^(tree[z][1]==y)) rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
void sg_insert(int now,int left,int right,int pos,int k)
{
    int ret=tot2;
    insert(root[now],0,k);
    if (ret!=tot2) splay(tot2,root[now]);
    if (left==right) return;
    int mid=left+right>>1;
    if (pos<=mid) sg_insert(ls[now],left,mid,pos,k);
    else sg_insert(rs[now],mid+1,right,pos,k);
}
void get_rank(int now,int k)
{
    if (!now) return;
    if (val[now]<k) {tmp+=size[tree[now][1]]+cnt[now];get_rank(tree[now][2],k);}
    else if (val[now]==k) {tmp+=size[tree[now][1]];return;}
    else get_rank(tree[now][1],k);
}
void sg_get_rank(int now,int left,int right,int l,int r,int x)
{
    if (left==l && right==r) {get_rank(root[now],x);tmp--;return;}
    int mid=left+right>>1;
    if (r<=mid) sg_get_rank(ls[now],left,mid,l,r,x);
    else if (l>=mid+1) sg_get_rank(rs[now],mid+1,right,l,r,x);
    else {sg_get_rank(ls[now],left,mid,l,mid,x);sg_get_rank(rs[now],mid+1,right,mid+1,r,x);}
}
int binary_search()
{
    int left=0,right=inf-1,ans,mid;
    while (left<=right)
    {
        mid=left+right>>1;tmp=0;
        sg_get_rank(tr_root,1,n,l,r,mid);
        if (tmp+1<=k) {ans=mid;left=mid+1;}
        else right=mid-1;
    }
    return ans;
}
void find_pre(int now,int k)
{
    if (!now) return;
    if (val[now]<k) {pre=now;find_pre(tree[now][2],k);}
    else find_pre(tree[now][1],k);
}
void find_sub(int now,int k)
{
    if (!now) return;
    if (val[now]>k) {sub=now;find_sub(tree[now][1],k);}
    else find_sub(tree[now][2],k);
}
void delete_(int now,int k)
{
    find_pre(root[now],k);find_sub(root[now],k);
    splay(pre,root[now]);
    splay(sub,tree[root[now]][2]);
    int x=root[now],y=tree[root[now]][2],z=tree[y][1];
    if (cnt[z]>1) {cnt[z]--;size[z]--;}
    else fath[z]=tree[y][1]=0;
    pushup(y);pushup(x);
}
void sg_delete(int now,int left,int right,int pos,int k)
{
    delete_(now,k);
    if (left==right) return;
    int mid=left+right>>1;
    if (pos<=mid) sg_delete(ls[now],left,mid,pos,k);
    else sg_delete(rs[now],mid+1,right,pos,k);
}
void sg_find_ps(int now,int left,int right,int l,int r,int k,int type)
{
    if (left==l && right==r)
    {
        if (type==1) {find_pre(root[now],k);tmp1=max(tmp1,val[pre]);}
        else {find_sub(root[now],k);tmp2=min(tmp2,val[sub]);}
        return;
    }
    int mid=left+right>>1;
    if (r<=mid) sg_find_ps(ls[now],left,mid,l,r,k,type);
    else if (l>=mid+1) sg_find_ps(rs[now],mid+1,right,l,r,k,type);
    else {sg_find_ps(ls[now],left,mid,l,mid,k,type);sg_find_ps(rs[now],mid+1,right,mid+1,r,k,type);}
}
void sg_mn_modify(int now,int left,int right,int pos,int k)
{
    if (left==right) {mn[now]=k;return;}
    int mid=(left+right)>>1;
    if (pos<=mid) sg_mn_modify(ls[now],left,mid,pos,k);
    else sg_mn_modify(rs[now],mid+1,right,pos,k);
    mn[now]=min(mn[ls[now]],mn[rs[now]]);
}
int sg_mn_ask(int now,int left,int right,int l,int r)
{
    if (left==l && right==r) return mn[now];
    int mid=(left+right)>>1;
    if (r<=mid) return sg_mn_ask(ls[now],left,mid,l,r);
    else if (l>=mid+1) return sg_mn_ask(rs[now],mid+1,right,l,r);
    else return min(sg_mn_ask(ls[now],left,mid,l,mid),sg_mn_ask(rs[now],mid+1,right,mid+1,r));
}
int main()
{
    scanf("%d%d",&n,&m);
    sg_build(tr_root,1,n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&x[i]);k=x[i];
        sg_insert(tr_root,1,n,i,k);
        sg_mn_modify(tr_root,1,n,i,k);
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&type);
        if (type==1) {scanf("%d%d%d",&l,&r,&k);tmp=0;sg_get_rank(tr_root,1,n,l,r,k);printf("%d\n",tmp+1);}
        else if (type==2) {scanf("%d%d%d",&l,&r,&k);printf("%d\n",binary_search());}
        else if (type==3) {scanf("%d%d",&pos,&k);sg_delete(tr_root,1,n,pos,x[pos]);x[pos]=k;sg_insert(tr_root,1,n,pos,k);sg_mn_modify(tr_root,1,n,pos,k);}
        else if (type==4) {scanf("%d%d%d",&l,&r,&k);tmp1=0;sg_find_ps(tr_root,1,n,l,r,k,1);printf("%d\n",tmp1);}
        else 
        {
            scanf("%d%d%d",&l,&r,&k);
            if (k<0) printf("%d\n",sg_mn_ask(tr_root,1,n,l,r));
            else
            {
                tmp2=inf;
                sg_find_ps(tr_root,1,n,l,r,k,2);
                printf("%d\n",tmp2);
            }
        }
    }
    return 0;
}