2023河南萌新联赛第(六)场:河南理工大学-L 阴晴不定的大橘学长

2023河南萌新联赛第(六)场:河南理工大学-L 阴晴不定的大橘学长

https://ac.nowcoder.com/acm/contest/63602/L?&headNav=acm

文章目录

  • 2023河南萌新联赛第(六)场:河南理工大学-L 阴晴不定的大橘学长
    • 题意
    • 解题思路
    • 代码

题意

现在给你一个临界值 x x x,并给你 n n n个时刻,第 i i i个时刻的值是 a i a_i ai,对于任意的 [ l , r ] [l,r] [l,r]时间段内如果 ( ∑ i = l r a i ) ≥ x (\sum_{i=l}^ra_i)\ge x (i=lrai)x,说明在这个时间段内是合法的。 现在请你来编写程序求解从 1 1 1 n n n时刻内有多少时间段是合法的。
注意:只要时间段 [ l , r ] [l,r] [l,r] l l l r r r有一个不同,便可认定为不同时间段。

解题思路

先对于该序列求一个前缀和 p r e {pre} pre,确定区间 [ l , r ] [l,r] [l,r]合法表现为保证 p r e r − p r e l − 1 ≥ x pre_r-pre_{l-1}\ge x prerprel1x,变形一下,可以得到 p r e l − 1 ≤ p r e r − x pre_{l-1}\le pre_r-x prel1prerx,可以对于每个确定的 r r r,查找在它之前的 p r e l − 1 ≤ p r e r − x pre_l-1\le pre_r-x prel1prerx l l l,可以从值域线段树中求。可以先将数值离散化,从左往右扫,每处理完一个就加入值域线段树,注意最开始要加入 0 0 0保证 [ i , i ] ( a i ≥ x ) [i,i](a_i\ge x) [i,i](aix)也被计算。

代码

#include
#define ll long long
#define fi first
#define se second
using namespace std;
const int N=2e5+5;
ll ans,p[N];
ll t[N<<3];
ll n,k,a[N],b[N<<1],cnt;
mapma; 
void add(int x,int l,int r,int d){
	if(l==r){
		t[x]++;
		return ;
	}
	int mid=l+r>>1;
	if(d<=mid)add(x<<1,l,mid,d);
	else add(x<<1|1,mid+1,r,d);
	t[x]=t[x<<1]+t[x<<1|1];
}
ll query(int x,int l,int r,int R){
	if(r<=R){
		return t[x];
	}
	int mid=l+r>>1;
	if(R<=mid)return query(x<<1,l,mid,R);
	return query(x<<1,l,mid,R)+query(x<<1|1,mid+1,r,R);
}
int main(){
	cin>>n>>k;
	b[++cnt]=0;
	for(int i=1;i<=n;i++)cin>>a[i],p[i]=p[i-1]+a[i],b[++cnt]=p[i]-k,b[++cnt]=p[i];
	sort(b+1,b+cnt+1);
	cnt=unique(b+1,b+cnt+1)-b-1;
	for(int i=1;i<=cnt;i++){
		ma[b[i]]=i;
	}
	add(1,1,cnt,ma[0]);
	for(int j=1;j<=n;j++){
		ans+=query(1,1,cnt,ma[p[j]-k]);
		add(1,1,cnt,ma[p[j]]);
	}
	cout<

你可能感兴趣的:(2023河南萌新联赛,算法,数据结构,线段树,c++)