2017ICPC西安 H Arrangement for Contests

题意:有n重问题,难度i的题目个数为ai个,每套题目有k个题且题目难度必须连续,问最多可以有多少套题目

贪心,每次尽量选最靠前的连续区间,用线段树维护一下。

#include
#include
#include
using namespace std;
#define ll long long
const int maxm = 100005;
const int INF = 1e9 + 7;
struct node
{
	int l, r, mi;
	ll sum, lazy;
}tr[maxm * 8];
int a[maxm];
void make(int l, int r, int num)
{
	tr[num].l = l, tr[num].r = r;
	tr[num].lazy = 0;
	if (l == r)
	{
		tr[num].mi = tr[num].sum = a[l];
		return;
	}
	int mid = (l + r) / 2;
	make(l, mid, num * 2);
	make(mid + 1, r, num * 2 + 1);
	tr[num].mi = min(tr[num * 2].mi, tr[num * 2 + 1].mi);
	tr[num].sum = tr[num * 2].sum + tr[num * 2 + 1].sum;
}
void down(int x)
{
	if (tr[x].l != tr[x].r)
		tr[x * 2].lazy = tr[x * 2 + 1].lazy = tr[x].lazy;
	tr[x].sum -= tr[x].lazy*(tr[x].r - tr[x].l + 1);
	tr[x].mi -= tr[x].lazy, tr[x].lazy = 0;
}
void update(int l, int r, int num,int val)
{
	if (tr[num].lazy) down(num);
	if (tr[num].l >= l&&tr[num].r <= r)
	{
		tr[num].lazy = val;
		down(num);
		return;
	}
	int mid = (tr[num].l + tr[num].r) / 2;
	if (mid >= r) update(l, r, num * 2, val);
	else if (mid < l) update(l, r, num * 2 + 1, val);
	else
	{
		update(l, mid, num * 2, val);
		update(mid + 1, r, num * 2 + 1, val);
	}
	tr[num].sum = tr[num * 2].sum + tr[num * 2 + 1].sum;
	tr[num].mi = min(tr[num * 2].mi, tr[num * 2 + 1].mi);
}
int query(int l, int r, int num)
{
	if (tr[num].lazy) down(num);
	if (tr[num].l >= l&&tr[num].r <= r)
		return tr[num].mi;
	int mid = (tr[num].l + tr[num].r) / 2, ans;
	if (mid >= r)
		ans = query(l, r, num * 2);
	else if (mid < l)
		ans = query(l, r, num * 2 + 1);
	else ans = min(query(l, mid, num * 2), query(mid + 1, r, num * 2 + 1));
	return ans;
}
int main()
{
	int n, i, j, k, sum, t, now, ans;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d", &n, &k);
		for (i = 1;i <= n;i++)
			scanf("%d", &a[i]);
		make(1, n, 1);
		i = 1, ans = 0;
		while (1)
		{
			while (i + k - 1 <= n && (now = query(i, i + k - 1, 1)) <= 0)
				i++;
			if (i + k - 1 > n) break;
			ans += now;
			update(i, i + k - 1, 1, now);
		}
		printf("%d\n", ans);
	}
	return 0;
}

 

你可能感兴趣的:(线段树)