2019.01.23【BZOJ3337】ORZJRY I(FHQ_treap实现ODT)

传送门


解析:

这种题无脑压节点,剩下的无脑写平衡树暴力就行了。

平衡树做不了的提出来数组做就行了。

没什么难度。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define cs const

namespace IO{
	namespace IOONLY{
		cs int Rlen=1<<20|1;
		char buf[Rlen],*p1,*p2;
	}
	inline char get_char(){
		using namespace IOONLY;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline int getint(){
		re char c;
		while(!isdigit(c=gc()));re int num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num;
	}
}
using namespace IO;

inline unsigned int Rand(){
    static unsigned int state0=19491001;
    state0^=(state0<<13);
    state0^=(state0>>17);
    state0^=(state0<<5);
    return state0; 
}

cs int N=500005,INF=0x7fffffff;

namespace FHQ_treap{
	namespace Vars{
		int son[N][2];
		bool rev[N];
		ll sum[N];
		int val[N],mx[N],mn[N],add[N];
		int siz[N],cnt[N];
		int tot;
	}
	inline int newnode(cs int _val,cs int _cnt=1){
		using namespace Vars;
		int now=++tot;
		val[now]=mn[now]=mx[now]=_val;
		sum[now]=(ll)_val*_cnt;
		siz[now]=cnt[now]=_cnt;
		return now;
	}
	
	inline void pushup(int now){
		using namespace Vars;
		siz[now]=siz[son[now][0]]+siz[son[now][1]]+cnt[now];
		sum[now]=sum[son[now][0]]+sum[son[now][1]]+(ll)val[now]*cnt[now];
		mn[now]=min(val[now],min(mn[son[now][0]],mn[son[now][1]]));
		mx[now]=max(val[now],max(mx[son[now][0]],mx[son[now][1]]));
	}
	
	inline void pushrev(int now){
		using namespace Vars;
		rev[now]^=1;
		swap(son[now][0],son[now][1]);
	}
	
	inline void pushadd(int now,int v){
		using namespace Vars;
		add[now]+=v;
		val[now]+=v;
		mx[now]+=v;
		mn[now]+=v;
		sum[now]+=(ll)siz[now]*v;
	}
	
	inline void pushdown(int now){
		using namespace Vars;
		if(rev[now]){
			if(son[now][0])pushrev(son[now][0]);
			if(son[now][1])pushrev(son[now][1]);
			rev[now]=0;
		}
		if(add[now]){
			if(son[now][0])pushadd(son[now][0],add[now]);
			if(son[now][1])pushadd(son[now][1],add[now]);
			add[now]=0;
		}
	}
	
	pair<int,int> split(int now,cs int &key){
		using namespace Vars;
		if(!now)return make_pair(0,0);
		pair<int,int> res;
		pushdown(now);
		if(siz[son[now][0]]+cnt[now]<=key){
			res=split(son[now][1],key-siz[son[now][0]]-cnt[now]);
			son[now][1]=res.first;
			res.first=now;
		}
		else {
			res=split(son[now][0],key);
			son[now][0]=res.second;
			res.second=now;
		}
		pushup(now);
		return res;
	}
	
	int merge(int lc,int rc){
		using namespace Vars;
		if(!lc||!rc)return lc+rc;
		pushdown(lc);
		pushdown(rc);
		if(Rand()*siz[lc]>Rand()*siz[rc]){
			son[lc][1]=merge(son[lc][1],rc);
			pushup(lc);
			return lc;
		}
		else {
			son[rc][0]=merge(lc,son[rc][0]);
			pushup(rc);
			return rc;
		}
	}
	
	int findlef(int now,int red){
		using namespace Vars;
		if(son[now][0]){
			int re tmp=findlef(son[now][0],red);
			pushup(now);
			return tmp;
		}
		else {
			cnt[now]-=red;
			pushup(now);
			return val[now];
		}
	}
	
	pair<int,int> Get(int now,int key){
		using namespace Vars;
		pair<int,int> res=split(now,key);
		int sz=key-siz[res.first];
		if(sz)res.first=merge(res.first,newnode(findlef(res.second,sz),sz));
		return res;
	}
	
	vector<pair<ll,int> >vec;
	void inorder_dfs(int now){
		using namespace Vars;
		if(!now)return ;
		pushdown(now);
		inorder_dfs(son[now][0]);
		vec.push_back(make_pair(val[now],cnt[now]));
		inorder_dfs(son[now][1]);
	}
	inline void travel(int now){
		vec.clear();
		inorder_dfs(now);
	}
}
using namespace FHQ_treap;
int rt;

inline void insert(int pos,int val){
	pair<int,int> res=Get(rt,pos);
	rt=merge(res.first,merge(newnode(val,1),res.second)); 
}

inline void erase(int pos){
	pair<int,int> res1=Get(rt,pos-1);
	pair<int,int> res2=Get(res1.second,1);
	rt=merge(res1.first,res2.second); 
}

inline void reverse(int l,int r){
	pair<int,int> res1=Get(rt,l-1);
	pair<int,int> res2=Get(res1.second,r-l+1);
	pushrev(res2.first);
	rt=merge(res1.first,merge(res2.first,res2.second));
}

inline void move(int l,int r,int k){
	pair<int,int> res1=Get(rt,l-1);
	pair<int,int> res2=Get(res1.second,r-l+1-k);
	pair<int,int> res3=Get(res2.second,k);
	rt=merge(merge(res1.first,res3.first),merge(res2.first,res3.second));
}

inline void add(int l,int r,int val){
	pair<int,int> res1=Get(rt,l-1);
	pair<int,int> res2=Get(res1.second,r-l+1);
	pushadd(res2.first,val);
	rt=merge(res1.first,merge(res2.first,res2.second));
}

inline void cover(int l,int r,int val){
	pair<int,int> res1=Get(rt,l-1);
	pair<int,int> res2=Get(res1.second,r-l+1);
	rt=merge(res1.first,merge(newnode(val,r-l+1),res2.second));
}

inline ll query_sum(int l,int r){
	pair<int,int> res1=Get(rt,l-1);
	pair<int,int> res2=Get(res1.second,r-l+1);
	ll res=Vars::sum[res2.first];
	rt=merge(res1.first,merge(res2.first,res2.second));
	return res;
}

inline int Min_Max(int l,int r){
	pair<int,int> res1=Get(rt,l-1);
	pair<int,int> res2=Get(res1.second,r-l+1);
	int res=Vars::mx[res2.first]-Vars::mn[res2.first];
	rt=merge(res1.first,merge(res2.first,res2.second));
	return res;
}

inline int nearest(int l,int r,int val){
	pair<int,int> res1=Get(rt,l-1);
	pair<int,int> res2=Get(res1.second,r-l+1);
	travel(res2.first);rt=merge(res1.first,merge(res2.first,res2.second));
	re int res=INF;
	for(int re i=0;i<vec.size();++i)res=min((ll)res,abs(val-vec[i].first));
	return res;
}

inline int query_Kth(int l,int r,int k){
	pair<int,int> res1=Get(rt,l-1);
	pair<int,int> res2=Get(res1.second,r-l+1);
	travel(res2.first);rt=merge(res1.first,merge(res2.first,res2.second));
	sort(vec.begin(),vec.end());
	re int res,i=0;
	while(true){
		k-=vec[i].second;
		if(k<=0)return vec[i].first;
		++i;
	}
}

inline int query_Rank(int l,int r,int val){
	pair<int,int> res1=Get(rt,l-1);
	pair<int,int> res2=Get(res1.second,r-l+1);
	travel(res2.first);rt=merge(res1.first,merge(res2.first,res2.second));
	re int cnt=0;
	for(int re i=0;i<vec.size();++i)cnt+=vec[i].first<val?vec[i].second:0;
	return cnt;
}

int n,m;
signed main(){
	Vars::mn[0]=INF,Vars::mx[0]=-INF;
	n=getint();
	for(int re i=1;i<=n;++i)rt=merge(rt,newnode(getint()));
	m=getint();
	while(m--){
		int x,y,val;
		switch(getint()){
			case 1:x=getint();val=getint();insert(x,val);break;
			case 2:erase(getint());break;
			case 3:x=getint(),y=getint();reverse(x,y);break;
			case 4:x=getint(),y=getint(),val=getint();move(x,y,val);break;
			case 5:x=getint(),y=getint(),val=getint();add(x,y,val);break;
			case 6:x=getint(),y=getint(),val=getint();cover(x,y,val);break;
			case 7:x=getint(),y=getint();cout<<query_sum(x,y)<<'\n';break;
			case 8:x=getint(),y=getint();cout<<Min_Max(x,y)<<'\n';break;
			case 9:x=getint(),y=getint(),val=getint();cout<<nearest(x,y,val)<<'\n';break;
			case 10:x=getint(),y=getint(),val=getint();cout<<query_Kth(x,y,val)<<'\n';break;
			case 11:x=getint(),y=getint(),val=getint();cout<<query_Rank(x,y,val)<<'\n';break;
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值