Description
有n个怪物排成一排,他们的生命值各不相同,asuka有一个叫做“千方残光剑”的技能,可以先秒杀掉y个怪物,然后对任意个怪物造成总量小于等于x点的伤害,但是如果不打死怪物就不会有经验,而asuka又有强迫症,他想保证自己最后杀掉的怪物是相邻的(是一整段的),那么释放一次技能最多能杀死多少个怪物呢?
Input
第一行输入一个t,t<=5代表数据组数。
对于每一组,第一行输入一个n,代表怪物个数。
第二行有n个数字,代表每个怪物的生命值,它们各不相同且ai<=n。
第三行一个整数x意义如题意。
第四行一个整数y意义如题意。
n<=100000。
Output
对于每一组输出一个整数x代表能够选取的怪物的最大数量。
Sample Input
1
5
1 2 3 4 5
扫描二维码关注公众号,回复:
2623535 查看本文章
7
1
Sample Output
4
Source
“科林明伦杯”计算机学院2018年程序设计竞赛
解题分析
选取最长的连续区间,使去掉最大的 个数字后的区间和不大于 。
尺取法(双指针 , )选择连续区间,不断右移 以更新区间;求去掉前 大数字后的区间和,可建一棵权值线段树(甚至不用离散化),维护区间数字个数 与区间和 ,可在 的时间找到第 大数的位置,此时左侧数字和即为所求。
若当前区间 去掉前 大数字后的区间和大于 ,可使 右移,缩短区间至满足要求后,更新最大区间长度。
总时间复杂度 。
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#define LL long long
using namespace std;
const int MAXN = 100010;
LL x;
int n, y, a[MAXN];
template<typename T> inline void Read(T &x) {
char ch = getchar(); x = 0;
for (; ch<'0'; ch = getchar());
for (; ch >= '0'; ch = getchar()) x = x * 10 + ch - '0';
}
struct STree{int l, r, num; LL sum;}st[MAXN << 2];
#define lson p << 1
#define rson p << 1 | 1
#define l(x) st[x].l
#define r(x) st[x].r
#define sum(x) st[x].sum
#define num(x) st[x].num
void build(int p, int l, int r)
{
l(p) = l, r(p) = r;
if(l == r){
sum(p) = num(p) = 0;
return;
}
int mid = (l + r) >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
sum(p) = sum(lson) + sum(rson);
num(p) = num(lson) + num(rson);
}
void change(int p, int x, int d)
{
if(l(p) == r(p)){
sum(p) = d ? x : 0;
num(p) = d;
return;
}
int mid = (l(p) + r(p)) >> 1;
if(x <= mid) change(lson, x, d);
else change(rson, x, d);
sum(p) = sum(lson) + sum(rson);
num(p) = num(lson) + num(rson);
}
LL ask(int p, int k)
{
if(k == num(p)) return 0;
LL ans = 0;
if(num(rson) > k) ans += sum(lson) + ask(rson, k);
else if(num(rson) < k) ans += ask(lson, k - num(rson));
else return sum(lson);
return ans;
}
int main()
{
int T; Read(T);
while(T --){
Read(n);
for(int i = 1; i <= n; i ++) Read(a[i]);
Read(x); Read(y);
if(y >= n){
cout << n << endl;
continue;
}
build(1, 0, n);
for(int i = 1; i <= y; i ++) change(1, a[i], 1);
int l = 1, ans = y;
for(int r = y + 1; r <= n; r ++){
change(1, a[r], 1);
while(x < ask(1, y)) change(1, a[l ++], 0);
ans = max(ans, r - l + 1);
}
cout << ans << endl;
}
return 0;
}