HOJ contests 15 I

本文介绍了一个经典的区间查询问题——美丽花园。题目要求找出所有美丽的花园区间,即满足一定长度和总美丽值条件的连续花朵序列。文章提供了一种有效的解法思路,利用离散化和树状数组进行优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Beautiful Garden

Time limit : 3 sMemory limit : 512 mb
  
64bit Integer Format : %lld

Problem Description

Long long ago, there was a garden where grew N flowers. Flowers were all in a line and each had a beautiful value(integer value), say a1 a2 …aN from left to right. Remember that some flowers could be ugly so that its beautiful value could be zero or negative.

One day, someone passed by the garden and he wanted to know how many beautiful intervals there were. A interval is continuous flowers from P to Q(P <= Q), and it is beautiful if and only if Q – P + 1 >= L and aP + a(P+1) + … + aQ>= M. Can you solve this old problem?

Input

There is only one integer T(1< = T <= 100) in the first line.And then comes T test cases.

For each test case, there are three integers  N(1 <= N <= 10000), L(1 <= L <= N) and M(-100000 <= M <= 100000) in the first line, and N integers a1, a2, …, aN(-100000 <= ai<= 100000) in the second line.

Output

Print the answer in the single line for each test case.

Sample Input

3

1 1 1

1

4 2 3

1 2 3 4

6 3 -7

-1 -2 -3 4 -5 6

Sample Output

1

6

10


题意:给出N个数a[1],a[2]...a[N], 对于一个区间[P,Q], 若Q-P+1 >= L, 并且a[P] + a[P+1] + ... + a[Q] >= M,则区间[P,Q]为beautiful区间,
问有多少beautiful区间。


题解:离散化一下  然后for右端点  用树状数组维护左端点


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,m,l;
int c[10005],num[10005],cnt,a[10005],sum[10005];
void change(int pos,int x){
	while(pos<=cnt){
		c[pos]+=x;
		pos+=(pos&-pos);
	}
}
int sums(int pos){
	int ss=0;
	while(pos>0){
		ss+=c[pos];
		pos-=(pos&-pos);
	}
	return ss;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%d",&n,&l,&m);
		int i,j,k,ans=0;
		cnt=0;
		num[++cnt]=0;
		memset(c,0,sizeof(c)); 
		for(i=1;i<=n;i++){
			scanf("%d",&a[i]);
			sum[i]=sum[i-1]+a[i];
			num[++cnt]=sum[i];
		}
		sort(num+1,num+1+cnt);
		cnt=unique(num+1,num+1+cnt)-num-1;
		change(lower_bound(num+1,num+1+cnt,0)-num,1);
		for(i=l;i<=n;i++){
			int mr=lower_bound(num+1,num+1+cnt,sum[i]-m)-num;
			if(num[mr]!=sum[i]-m)mr--;
			ans+=sums(mr);
			change(lower_bound(num+1,num+1+cnt,sum[i-l+1])-num,1);
		}
		printf("%d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值