【无旋treap】礼物(2022.5.28)
和洛谷上的P5459 [BJOI2016]回转寿司不能说一模一样,只能说完全相同(这题能评紫?)
题目描述
1.1 题目描述
现在有一排  n  个礼物,每个礼物有一个价格  pi,不过这是一家神奇的商店,店长可能
会倒贴来出售一些礼物,也就是说价格可能为负数。
小Y 想给女朋友买礼物,为了表达心意,他希望购买的礼物总价不小于  L,但是也不能
买得太贵,因为总价大于  R  会惹女朋友生气。然而作为一个直男,小Y  确实不知道应该如
何选择,于是他想出了一个办法——选择若干紧邻连续的礼物进行购买。他现在希望知道自
己一共有多少种合适的购买方案。
1.2 输入格式
第一行为三个整数  n, L, R,含义如题意所述;
接下来一行  n  个整数,第  i  个整数为  pi,表示第  i  个礼物的价格。
1.3 输出格式
仅一行一个整数,表示满足条件的方案数。
1.4 样例输入
 5 5 8 
3 3 -2 1 3 
1.5 样例输出
4 
1.6 样例解释
依次对礼物编号为1,2,3,4,5,则满足条件的方案有 {1,2}, {1,2,3,4}, {1,2,3,4,5}, {2,3,4,5}。
1.7 数据范围与约定
对于前20%的数据满足  n≤1000;
对于另外20%的数据满足  pi  非负。
对于100%的数据满足1≤n≤100000,1≤L≤R≤109,|pi|≤100000。
解思
每次新加入一个数,要把前面所有数的前缀和都加上这个数,考虑前面不加而是将答案的区间平移,于是想到支持单点修改,区间动态查询的平衡树,FHQ无旋treap(有旋板子现在还没过2333),据说也有用树状数组离散化和CDQ分治的...
关于FHQ无旋treap参见【无旋treap hash】匹配(2022.5.21) _
平衡树代码如下:
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
	int f=1,j=0;
	char w=getchar();
	while(w>'9'||w<'0'){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(w>='0'&&w<='9'){
		j=(j<<3)+(j<<1)+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=100100;
int n,L,R,now,root,ans;
int ln[N],sum[N],num[N],size[N],ls[N],rs[N],tail;
inline void update(int nown){
	size[nown]=size[ls[nown]]+size[rs[nown]]+ln[nown];
	return ;
}
void split(int nown,int &l,int &r,int val){
	if(nown==0){
		l=r=0;
		return ;
	}
	if(sum[nown]<=val)l=nown,split(rs[nown],rs[nown],r,val);
	else r=nown,split(ls[nown],l,ls[nown],val);
	update(nown);
	return ;
}
void merge(int &k,int l,int r){
	if(l==0||r==0){
		k=l+r;
		return ;
	}
	if(num[l]>num[r])k=l,merge(rs[l],rs[l],r);
	else k=r,merge(ls[r],l,ls[r]);
	update(k); 
	return ;
}
inline int newpoint(int k){
	sum[++tail]=k;
	ln[tail]=1;
	num[tail]=rand();
	return tail;
}
signed main(){
	//freopen("gift.in","r",stdin);
	//freopen("gift.out","w",stdout);
	srand(time(NULL));
	n=read();L=read();R=read();
	for(int i=1;i<=n;i++){
		int x=read(),y;
		now+=x;y=x-now;
		int l,mid=0,r;
		split(root,l,r,y);
		split(l,l,mid,y-1);
		if(mid!=0)ln[mid]++;
		else mid=newpoint(y);
		update(mid);//------------
		merge(root,l,mid);
		merge(root,root,r);
		split(root,l,r,R-now);
		split(l,l,mid,L-1-now);
		ans+=size[mid];
		merge(root,l,mid);
		merge(root,root,r);
	}
	printf("%lld",ans);
	return 0;
}
/*
5 5 8
3 3 -2 1 3
*/

                
            
        
浙公网安备 33010602011771号