hdu6037 Rikka with Sequence

传送门
参考博客
Scape:裸可持久化平衡树
其实也就是一个 f h q   t r e a p fhq\ treap fhq treap,只不过空间限得很死。
操作1:分出 [ l , r ] [l,r] [l,r]区间,返回和。
操作2:找到 [ l − k , l − 1 ] [l-k,l-1] [lk,l1],合并若干次后剩下一点,再合并。前者的过程可以倍增,因为是相同的区间不断合并,类似于快速幂。
操作3:用原树拆出 [ l , r ] [l,r] [l,r],再把现在的树拆掉 [ l , r ] [l,r] [l,r],合并一下即可。
①比较扯淡的是由于空间可能会爆,操作一定次数后要暴力重构一下。
②为了避免重复的随机因子,采用动态比较。即 m e r g e merge merge的时候取随机因子然后这样:

inline int rnd(){return rand()<<15|rand();}
inline int check(int x,int y){return rnd()%(x+y)<x;}
int merge(int a,int b){
	if(!a||!b) return a|b;
	int p=++tot;
	if(check(T[a].siz,T[b].siz)) T[p]=T[a],T[p].r=merge(T[p].r,b);
	else T[p]=T[b],T[p].l=merge(a,T[p].l);
	return pushup(p),p;
}

祝代码愉快。

#include
#define lc T[rt].l
#define rc T[rt].r
using namespace std;
typedef long long ll;
const int maxn=2e5+10,maxm=1900000,MX=1800010;
int n,m,op,l,r,k,tot,a[maxn],top=0,root,ROOT;
struct node{int l,r,siz,rd,val;ll sum;}T[maxm];
inline int rnd(){return rand()<<15|rand();}
inline int check(int x,int y){return rnd()%(x+y)<x;}
inline void print(ll x){
	if(x>9) print(x/10);
	putchar(x%10+'0');
}
inline int read(){
	int x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return x;
}
inline void pushup(int rt){
	T[rt].siz=T[lc].siz+T[rc].siz+1;
	T[rt].sum=T[lc].sum+T[rc].sum+T[rt].val;
}
inline int newnode(int VAL){
	++tot;T[tot].l=T[tot].r=0,T[tot].rd=rnd();
	T[tot].siz=1,T[tot].val=T[tot].sum=VAL;
	return tot;
}
int merge(int a,int b){
	if(!a||!b) return a|b;
	int p=++tot;
	if(check(T[a].siz,T[b].siz)) T[p]=T[a],T[p].r=merge(T[p].r,b);
	else T[p]=T[b],T[p].l=merge(a,T[p].l);
	return pushup(p),p;
}
inline int Merge(int a,int b){
	if(!a||!b) return a|b;
	if(T[a].rd>T[b].rd) return T[a].r=Merge(T[a].r,b),pushup(a),a;
	else return T[b].l=Merge(a,T[b].l),pushup(b),b;
}
void split(int rt,int rnk,int &x,int &y){
	if(!rt){x=y=0;return;}
	if(T[lc].siz<rnk) T[x=++tot]=T[rt],split(rc,rnk-T[lc].siz-1,T[x].r,y),pushup(x);
	else T[y=++tot]=T[rt],split(lc,rnk,x,T[y].l),pushup(y);
}
inline void query(int &rt,int l,int r){
	int L,M,R;
	split(rt,r,L,R),split(L,l-1,L,M);
	print(T[M].sum),putchar(10),rt=merge(L,merge(M,R));
}
inline void cpy(int &rt,int l,int r){
	int L,M,R,M2;
	split(ROOT,r,L,R),split(L,l-1,L,M);
	split(rt,r,L,R),split(L,l-1,L,M2);
	rt=Merge(L,Merge(M,R));
}
inline void upt(int &rt,int l,int r,int k){
	int L,R,M,M2;
	split(rt,l-1,L,R),split(L,l-k-1,L,M);
	while(T[M].siz<r-l+1) M=merge(M,M);
	split(M,r-l+1,M,M2),split(rt,r,L,R),split(L,l-1,L,M2);
	rt=merge(L,merge(M,R));
}
void build(int &rt,int l,int r){
	if(l>r){rt=0;return;}
	int mid=(l+r)>>1;rt=newnode(a[mid]);
	build(lc,l,mid-1),build(rc,mid+1,r),pushup(rt);
}
void dfs(int rt){if(!rt) return;dfs(lc),a[++top]=T[rt].val,dfs(rc);}
inline void rebuild(int &rt){tot=n,top=0,dfs(rt),build(rt,1,n);}
int main(){
	//freopen("hdu6087.in","r",stdin);
	srand(time(0)),n=read(),m=read();
	for(int i=1;i<=n;++i) a[i]=read();
	build(root,1,n),ROOT=root;
	while(m--){
		op=read(),l=read(),r=read();
		switch(op){
			case 1:query(root,l,r);break;
			case 2:k=read(),upt(root,l,r,k);break;
			case 3:cpy(root,l,r);break;
			default:break;
		}if(tot>MX) rebuild(root);
	}
}

你可能感兴趣的:(hdu6037 Rikka with Sequence)