Bzoj3196:Tyvj1730二逼平衡树:树套树,线段树套splay

10 篇文章 0 订阅
4 篇文章 0 订阅

题目链接:3196: Tyvj 1730 二逼平衡树

麻麻我终于会写树套树辣

这3个小时没白花QAQ

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1200010;
const int inf=1e9-1;
int tot=2,n,m,c[maxn],root[maxn];
struct seg{
	int l,r,rt;
	seg *lc,*rc;
	seg():rt(0){}
};
seg *Root=new seg();
struct Nodes{
	int c[2],fa,rev,s,num,val;
};
struct splay_tree{
	Nodes t[maxn];
	void push_up(int x){
		t[x].s=t[t[x].c[0]].s+t[t[x].c[1]].s+t[x].num;
	}
	void rotate(int p,int x){
        int mark= p==t[x].c[1];
        int y=t[p].c[mark^1],z=t[x].fa;
        if (t[z].c[0]==x) t[z].c[0]=p;
        if (t[z].c[1]==x) t[z].c[1]=p;
        if (y) t[y].fa=x;  t[x].c[mark]=y;
        t[p].fa=z; t[p].c[mark^1]=x; t[x].fa=p;
        push_up(x);
    }
	void splay(int rt,int p,int k){
        while (t[p].fa!=k){
            int x=t[p].fa,y=t[x].fa;
            if (y==k) rotate(p,x);
            else if (p==t[x].c[0]^x==t[y].c[0]) rotate(p,x),rotate(p,y);
            else rotate(x,y),rotate(p,x);
        } push_up(p);
        if (!k) root[rt]=p; return;
    }
	void ins(int rt,int val){
		int x=root[rt];
		if (!x){
			t[++tot].val=val;
			t[tot].num=t[tot].s=1;
			root[rt]=tot; return;
		}
		while (t[x].val!=val)
			if (t[x].val>val){if(t[x].c[0])x=t[x].c[0];else break;}
			else {if(t[x].c[1])x=t[x].c[1];else break;}
		if (t[x].val==val){t[x].num++;splay(rt,x,0);return;}
		t[++tot].val=val; t[tot].fa=x; t[tot].num=t[tot].s=1;
		if (val<t[x].val) t[x].c[0]=tot; else t[x].c[1]=tot;
		splay(rt,tot,0); return;
	}
	int find(int rt,int k){
		int x=root[rt];
		while (t[x].val!=k)
		    if (t[x].val>k){if(t[x].c[0])x=t[x].c[0];else break;}
		    else {if(t[x].c[1])x=t[x].c[1];else break;}
		splay(rt,x,0); return x;
	}
	int qrank(int rt,int k){
		int x=find(rt,k);
		if (t[x].val>=k) return t[t[x].c[0]].s;
		else return t[t[x].c[0]].s+t[x].num;
	}
	void del(int rt,int val){
		int x=root[rt];
		while (t[x].val!=val)
		    if (t[x].val>val){if(t[x].c[0])x=t[x].c[0];else break;}
			else{if (t[x].c[1])x=t[x].c[1];else break;}
		splay(rt,x,0);
		if (t[x].num>1){t[x].num--;return;}
		if (!t[x].c[0]){root[rt]=t[x].c[1];t[t[x].c[1]].fa=0;return;}
		if (!t[x].c[1]){root[rt]=t[x].c[0];t[t[x].c[0]].fa=0;return;}
		int y=t[x].c[0];
		while (t[y].c[1]) y=t[y].c[1];
		splay(rt,y,x);
		t[y].c[1]=t[x].c[1]; t[y].fa=0; t[t[y].c[1]].fa=y;
		push_up(y); root[rt]=y;
	}
	int prec(int rt,int val){
		int x=root[rt];
		while (t[x].val!=val)
		    if (t[x].val>val){if(t[x].c[0])x=t[x].c[0];else break;}
		    else{if (t[x].c[1])x=t[x].c[1];else break;}
		if (t[x].val==val){
			splay(rt,x,0);
			if (!t[x].c[0]) return 1;
			x=t[x].c[0];
			while (t[x].c[1]) x=t[x].c[1];
			return x;
		}
		while (t[x].fa&&t[x].val>val) x=t[x].fa;
		if (t[x].val<val) return x;
		return 1;
	}
	int succ(int rt,int val){
		int x=root[rt];
		while (t[x].val!=val)
		    if (t[x].val>val){if (t[x].c[0])x=t[x].c[0];else break;}
		    else{if (t[x].c[1])x=t[x].c[1];else break;}
		if (t[x].val==val){
			splay(rt,x,0);
			if (!t[x].c[1]) return 2;
			x=t[x].c[1];
			while (t[x].c[0]) x=t[x].c[0];
			return x;
		}
		while (t[x].fa&&t[x].val<val) x=t[x].fa;
		if (t[x].val>val) return x;
		return 2;
	}
}s;

void build(seg *p,int rt,int l,int r){
	p->rt=rt; p->l=l; p->r=r;
	for (int i=l;i<r;++i) s.ins(rt,c[i]);
	if (l+1==r){p->lc=p->rc=NULL;return;}
	else if (l+1<r){
		int mid=(l+r)>>1;
		p->lc=new seg();
		p->rc=new seg();
		if (l<mid) build(p->lc,rt<<1,l,mid);
		else p->lc=NULL;
		if (mid<r) build(p->rc,rt<<1|1,mid,r);
		else p->rc=NULL;
	}
}

int getrank(seg *p,int l,int r,int k){
	if (l<=p->l&&p->r<=r) return s.qrank(p->rt,k);
	int mid=(p->l+p->r)>>1,ret=0;
	if (l<mid) ret=getrank(p->lc,l,r,k);
	if (mid<r) ret+=getrank(p->rc,l,r,k);
	return ret;
}

void change(seg *p,int pos,int val){
	s.del(p->rt,c[pos]); s.ins(p->rt,val);
	if (p->l+1==p->r) return;
	int mid=(p->l+p->r)>>1;
	if (pos<mid) change(p->lc,pos,val);
	else change(p->rc,pos,val);
}

int qpre(seg *p,int l,int r,int val){
	if (l<=p->l&&p->r<=r){
		int x=s.prec(p->rt,val);
		if (s.t[x].val<val) return s.t[x].val;
		return -1;
	}
	int mid=(p->l+p->r)>>1,ret=-1;
	if (l<mid) ret=max(ret,qpre(p->lc,l,r,val));
	if (mid<r) ret=max(ret,qpre(p->rc,l,r,val));
	return ret;
}

int qsuc(seg *p,int l,int r,int val){
	if (l<=p->l&&p->r<=r){
		int x=s.succ(p->rt,val);
		if (s.t[x].val>val) return s.t[x].val;
		return inf;
	}
	int mid=(p->l+p->r)>>1,ret=inf;
	if (l<mid) ret=min(ret,qsuc(p->lc,l,r,val));
	if (mid<r) ret=min(ret,qsuc(p->rc,l,r,val));
	return ret;
}

int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;++i) scanf("%d",&c[i]);
	s.t[1].val=-1; s.t[2].val=inf;
	build(Root,1,1,n+1);
	for (int i=1;i<=m;++i){
		int opt,x,y,z;
		scanf("%d%d%d",&opt,&x,&y);
		if (opt!=3) scanf("%d",&z);
		if (opt==1) printf("%d\n",getrank(Root,x,y+1,z)+1);
		else if (opt==2){
			int L=0,R=1e8,ans=0;
			while (L<=R){
				int mid=(L+R)>>1;
				if(getrank(Root,x,y+1,mid)<z)ans=mid,L=mid+1;
				else R=mid-1;
			}printf("%d\n",ans);
		}else if (opt==3) change(Root,x,y),c[x]=y;
		else if (opt==4) printf("%d\n",qpre(Root,x,y+1,z));
		else if (opt==5) printf("%d\n",qsuc(Root,x,y+1,z));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值