3196: Tyvj 1730 二逼平衡树

10 篇文章 0 订阅
3 篇文章 0 订阅

人生第一道树套树的题,卡了3个小时。。。。。。。。

简直是人生耻辱啊。

目测从此患上了树套树恐惧症。

还有就是为毛我写的Treap这么慢(=。=)竟然跑了8秒多,感觉要跪啊。

还有这200多行的代码看得我好虚啊。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<cctype>
using namespace std;
const int N=50000+5;
const int M=2000000+5;
int lc[M],rc[M],key[M],sz[M],fix[M],cnt;
queue<int>q;
int id(){
    if(q.size()){
        int t=q.front();q.pop();
        return t;
    }else return ++cnt;
}
void pushup(int x){
    sz[x]=sz[lc[x]]+sz[rc[x]]+1;
}
void lturn(int &x){
    int k=rc[x];rc[x]=lc[k];lc[k]=x;sz[k]=sz[x];pushup(x);x=k;
}
void rturn(int &x){
    int k=lc[x];lc[x]=rc[k];rc[k]=x;sz[k]=sz[x];pushup(x);x=k;
}
struct treap{
    int root;
    treap(){
        root=0;
    }
    void insert(int &x,int v){
        if(!x){
            key[x=id()]=v;sz[x]=1;lc[x]=rc[x]=0;fix[x]=rand();
        }
        else{
            sz[x]++;
            if(v<key[x]){
            	insert(lc[x],v);
                if(fix[lc[x]]<fix[x])rturn(x);
            }else{
                insert(rc[x],v);
                if(fix[rc[x]]<fix[x])lturn(x);
            }
        }
    }
    void insert(int x){
        insert(root,x);
    }
    void del(int &x,int v){
    	if(!x)return;
        if(key[x]==v){
        	if(!lc[x]||!rc[x])q.push(x),x=lc[x]+rc[x];
            else if(fix[lc[x]]<fix[rc[x]])rturn(x),sz[x]--,del(rc[x],v);
            else lturn(x),sz[x]--,del(lc[x],v);
        }else{
        	sz[x]--;
            if(v<key[x])del(lc[x],v);
            else del(rc[x],v);
        }
    }
    void modify(int x,int y){
        del(root,x);
        insert(root,y);
    }
    int rank(int x,int k){
        if(!x)return 0;
        if(k<=key[x])return rank(lc[x],k);
        else return sz[lc[x]]+1+rank(rc[x],k);
    }
    int rank(int x){
        return rank(root,x);
    }
    int suc(int x,int k){
        if(!x)return k;
        if(key[x]<=k)return suc(rc[x],k);
        else{
            int r=suc(lc[x],k);
            if(r==k)return key[x];
            else return r;
        }
    }
    int suc(int k){
        return suc(root,k);
    }
    int pre(int x,int k){
        if(!x)return k;
        if(key[x]>=k)return pre(lc[x],k);
        else{
            int r=pre(rc[x],k);
            if(r==k)return key[x];
            else return r;
        }
    }
    int pre(int k){
        return pre(root,k);
    }
    void travel(int x){
        if(!x)return;
        travel(lc[x]);
        printf("%d ",key[x]);
        travel(rc[x]);
    }
    void travel(){
        travel(root);
    }
};
struct Node{
    int l,r,lc,rc;
    treap t;
};
struct SegmentTree{
    int cnt,root;
    Node tr[N<<2];
    SegmentTree(){
        cnt=0;
        root=0;
    }
    void build(int &o,int l,int r){
        o=++cnt;
        tr[o].l=l;tr[o].r=r;
        if(l==r)return;
        else{
            int mid=l+r>>1;
            build(tr[o].lc,l,mid);
            build(tr[o].rc,mid+1,r);
        }
    }
    void build(int n){
        build(root,1,n);
    }
    void insert(int o,int p,int x){
        tr[o].t.insert(x);
        int l=tr[o].l,r=tr[o].r;
        if(l==r)return;
        else{
            int mid=l+r>>1;
            if(p<=mid)insert(tr[o].lc,p,x);
            else insert(tr[o].rc,p,x);
        }
    }
    void modify(int o,int p,int x,int y){
        //printf("%d %d\n",x,y);
        tr[o].t.modify(x,y);
        int l=tr[o].l,r=tr[o].r;
        if(l==r)return;
        else{
            int mid=l+r>>1;
            if(p<=mid)modify(tr[o].lc,p,x,y);
            else modify(tr[o].rc,p,x,y);
        }
    }
    int rank(int o,int a,int b,int x){
        int l=tr[o].l,r=tr[o].r;
        if(l==a&&b==r)return tr[o].t.rank(x);
        else{
            int mid=l+r>>1;
            if(b<=mid)return rank(tr[o].lc,a,b,x);
            else if(mid<a)return rank(tr[o].rc,a,b,x);
            else return rank(tr[o].lc,a,mid,x)+rank(tr[o].rc,mid+1,b,x);
        }
    }
    int pre(int o,int a,int b,int x){
        int l=tr[o].l,r=tr[o].r;
        if(l==a&&b==r)return tr[o].t.pre(x);
        else{
            int mid=l+r>>1;
            if(b<=mid)return pre(tr[o].lc,a,b,x);
            else if(mid<a)return pre(tr[o].rc,a,b,x);
            else{
                int lans=pre(tr[o].lc,a,mid,x),rans=pre(tr[o].rc,mid+1,b,x);
                if(lans==x)return rans;
                if(rans==x)return lans;
                return max(lans,rans);
            }
        }
    }
    int suc(int o,int a,int b,int x){
        int l=tr[o].l,r=tr[o].r;
        if(l==a&&b==r)return tr[o].t.suc(x);
        else{
            int mid=l+r>>1;
            if(b<=mid)return suc(tr[o].lc,a,b,x);
            else if(mid<a)return suc(tr[o].rc,a,b,x);
            else{
                int lans=suc(tr[o].lc,a,mid,x),rans=suc(tr[o].rc,mid+1,b,x);
                if(lans==x)return rans;
                if(rans==x)return lans;
                return min(lans,rans);
            }
        }
    }
    void travel(int o){
        if(!o)return;
        printf("%d %d\n",tr[o].l,tr[o].r);
        tr[o].t.travel();putchar('\n');
        travel(tr[o].lc);travel(tr[o].rc);
    }
    void travel(){
        travel(root);
    }
}t;
int kth(int a,int b,int k){
    int l=0,r=(1e8);
    while(l<=r){
        int mid=l+r>>1;
        int rank=t.rank(1,a,b,mid);
        if(rank>=k)r=mid-1;
        else{
            if(t.rank(1,a,b,mid+1)>=k)return mid;
            else l=mid+1;
        }
    }
}
template<class T>void read(T &x){
    static char c;
    static bool f;
    for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1;
    for(x=0;isdigit(c);c=getchar())x=x*10+c-'0';
    if(f)x=-x;
}
int a[N];
int main(){
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    srand(34024902);
    int n,m;read(n);read(m);
    t.build(n);
    int l,r,k,opt;
    for(int i=1;i<=n;i++){
        read(a[i]);
        t.insert(1,i,a[i]);
    }
    //t.travel();
    while(m--){
        read(opt);
        if(opt==1){
            read(l);read(r);read(k);
            printf("%d\n",t.rank(1,l,r,k)+1);
        }else if(opt==2){
            read(l);read(r);read(k);
            printf("%d\n",kth(l,r,k));
        }else if(opt==3){
            read(l);read(k);
            t.modify(1,l,a[l],k);
            a[l]=k;
        }else if(opt==4){
            read(l);read(r);read(k);
            printf("%d\n",t.pre(1,l,r,k));
        }else if(opt==5){
            read(l);read(r);read(k);
            printf("%d\n",t.suc(1,l,r,k));
        }
    }
    return 0;
}
    


为了洗刷这一耻辱,我决定……

用SBT重写一遍!

然后发现,还是跑了6秒多TAT。

好慢啊。。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cctype>
using namespace std;
const int N=50000+5;
const int M=2000000+5;
int lc[M],rc[M],key[M],sz[M],cnt;
queue<int>q;
int id(){
    if(q.size()){
        int t=q.front();q.pop();
        return t;
    }else return ++cnt;
}
void pushup(int x){
    sz[x]=sz[lc[x]]+sz[rc[x]]+1;
}
void lturn(int &x){
    int k=rc[x];rc[x]=lc[k];lc[k]=x;sz[k]=sz[x];pushup(x);x=k;
}
void rturn(int &x){
    int k=lc[x];lc[x]=rc[k];rc[k]=x;sz[k]=sz[x];pushup(x);x=k;
}
void maintain(int &x,bool flag){
	if(!flag){
		if(sz[lc[lc[x]]]>sz[rc[x]])rturn(x);
		else if(sz[rc[lc[x]]]>sz[rc[x]]){
			lturn(lc[x]);
			rturn(x);
		}else return;
	}else{
		if(sz[rc[rc[x]]]>sz[lc[x]])lturn(x);
		else if(sz[lc[rc[x]]]>sz[lc[x]]){
			rturn(rc[x]);
			lturn(x);
		}else return;
	}
	maintain(lc[x],false);maintain(rc[x],true);
	maintain(x,true);maintain(x,false);
}
struct SBT{
    int root;
    SBT(){
        root=0;
    }
    void insert(int &x,int v){
        if(!x){
            key[x=id()]=v;sz[x]=1;lc[x]=rc[x]=0;
        }
        else{
            sz[x]++;
            if(v<key[x])insert(lc[x],v);
            else insert(rc[x],v);
            maintain(x,v>=key[x]);
        }
    }
    void insert(int x){
        insert(root,x);
    }
    int del(int &x,int v){
    	sz[x]--;
        if(key[x]==v||(v<key[x]&&!lc[x])||(v>key[x]&&!rc[x])){
        	int r=key[x];
        	if(!lc[x]||!rc[x])x=lc[x]+rc[x];
        	else key[x]=del(lc[x],key[x]+1);
        	return r;
        }else{
        	if(v<key[x])return del(lc[x],v);
        	else return del(rc[x],v);
        }
    }
    void modify(int x,int y){
        del(root,x);
        insert(root,y);
    }
    int rank(int x,int k){
        if(!x)return 0;
        if(k<=key[x])return rank(lc[x],k);
        else return sz[lc[x]]+1+rank(rc[x],k);
    }
    int rank(int x){
        return rank(root,x);
    }
    int suc(int x,int k){
        if(!x)return k;
        if(key[x]<=k)return suc(rc[x],k);
        else{
            int r=suc(lc[x],k);
            if(r==k)return key[x];
            else return r;
        }
    }
    int suc(int k){
        return suc(root,k);
    }
    int pre(int x,int k){
        if(!x)return k;
        if(key[x]>=k)return pre(lc[x],k);
        else{
            int r=pre(rc[x],k);
            if(r==k)return key[x];
            else return r;
        }
    }
    int pre(int k){
        return pre(root,k);
    }
    void travel(int x){
        if(!x)return;
        travel(lc[x]);
        printf("%d ",key[x]);
        travel(rc[x]);
    }
    void travel(){
        travel(root);
    }
};
struct Node{
    int l,r,lc,rc;
    SBT t;
};
struct SegmentTree{
    int cnt,root;
    Node tr[N<<2];
    SegmentTree(){
        cnt=0;
        root=0;
    }
    void build(int &o,int l,int r){
        o=++cnt;
        tr[o].l=l;tr[o].r=r;
        if(l==r)return;
        else{
            int mid=l+r>>1;
            build(tr[o].lc,l,mid);
            build(tr[o].rc,mid+1,r);
        }
    }
    void build(int n){
        build(root,1,n);
    }
    void insert(int o,int p,int x){
        tr[o].t.insert(x);
        int l=tr[o].l,r=tr[o].r;
        if(l==r)return;
        else{
            int mid=l+r>>1;
            if(p<=mid)insert(tr[o].lc,p,x);
            else insert(tr[o].rc,p,x);
        }
    }
    void modify(int o,int p,int x,int y){
        //printf("%d %d\n",x,y);
        tr[o].t.modify(x,y);
        int l=tr[o].l,r=tr[o].r;
        if(l==r)return;
        else{
            int mid=l+r>>1;
            if(p<=mid)modify(tr[o].lc,p,x,y);
            else modify(tr[o].rc,p,x,y);
        }
    }
    int rank(int o,int a,int b,int x){
        int l=tr[o].l,r=tr[o].r;
        if(l==a&&b==r)return tr[o].t.rank(x);
        else{
            int mid=l+r>>1;
            if(b<=mid)return rank(tr[o].lc,a,b,x);
            else if(mid<a)return rank(tr[o].rc,a,b,x);
            else return rank(tr[o].lc,a,mid,x)+rank(tr[o].rc,mid+1,b,x);
        }
    }
    int pre(int o,int a,int b,int x){
        int l=tr[o].l,r=tr[o].r;
        if(l==a&&b==r)return tr[o].t.pre(x);
        else{
            int mid=l+r>>1;
            if(b<=mid)return pre(tr[o].lc,a,b,x);
            else if(mid<a)return pre(tr[o].rc,a,b,x);
            else{
                int lans=pre(tr[o].lc,a,mid,x),rans=pre(tr[o].rc,mid+1,b,x);
                if(lans==x)return rans;
                if(rans==x)return lans;
                return max(lans,rans);
            }
        }
    }
    int suc(int o,int a,int b,int x){
        int l=tr[o].l,r=tr[o].r;
        if(l==a&&b==r)return tr[o].t.suc(x);
        else{
            int mid=l+r>>1;
            if(b<=mid)return suc(tr[o].lc,a,b,x);
            else if(mid<a)return suc(tr[o].rc,a,b,x);
            else{
                int lans=suc(tr[o].lc,a,mid,x),rans=suc(tr[o].rc,mid+1,b,x);
                if(lans==x)return rans;
                if(rans==x)return lans;
                return min(lans,rans);
            }
        }
    }
    void travel(int o){
        if(!o)return;
        printf("%d %d\n",tr[o].l,tr[o].r);
        tr[o].t.travel();putchar('\n');
        travel(tr[o].lc);travel(tr[o].rc);
    }
    void travel(){
        travel(root);
    }
}t;
int kth(int a,int b,int k){
    int l=0,r=(1e8);
    while(l<=r){
        int mid=l+r>>1;
        int rank=t.rank(1,a,b,mid);
        if(rank>=k)r=mid-1;
        else{
            if(t.rank(1,a,b,mid+1)>=k)return mid;
            else l=mid+1;
        }
    }
}
template<class T>void read(T &x){
    static char c;
    static bool f;
    for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1;
    for(x=0;isdigit(c);c=getchar())x=x*10+c-'0';
    if(f)x=-x;
}
int a[N];
int main(){
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    int n,m;read(n);read(m);
    t.build(n);
    int l,r,k,opt;
    for(int i=1;i<=n;i++){
        read(a[i]);
        t.insert(1,i,a[i]);
    }
    //t.travel();
    while(m--){
        read(opt);
        if(opt==1){
            read(l);read(r);read(k);
            printf("%d\n",t.rank(1,l,r,k)+1);
        }else if(opt==2){
            read(l);read(r);read(k);
            printf("%d\n",kth(l,r,k));
        }else if(opt==3){
            read(l);read(k);
            t.modify(1,l,a[l],k);
            a[l]=k;
        }else if(opt==4){
            read(l);read(r);read(k);
            printf("%d\n",t.pre(1,l,r,k));
        }else if(opt==5){
            read(l);read(r);read(k);
            printf("%d\n",t.suc(1,l,r,k));
        }
    }
    return 0;
}
    



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值