洛谷P1083 二分答案+差分+前缀和

题解

给你一组数,数量为n,有m组操作,每一组操作对某一范围的数进行-d
每一组操作都有严格的先后顺序,问:最先使这组数中有负数的操作,是哪一组(即标号最小的操作)
不存在输出0,存在输出-1,和该标号
二分答案
差分:区间加和和区间减数
前缀和:还原区间修改的结果

#include<iostream>
#include<vector>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define maxn 1000005
#define inf 2147483647

int a[maxn], b[maxn];
int l[maxn], r[maxn], d[maxn];
ll sum[maxn];
int n, m, ans;

bool check(int k)
{
	for (int i = 1; i <= n; i++)b[i] = a[i] - a[i - 1];
	for (int i = 1; i <= k; i++)
		b[l[i]] -= d[i], b[r[i] + 1] += d[i];
	for (int i = 1; i <= n; i++)
	{
		sum[i] = b[i] + sum[i - 1];
		if (sum[i]<0)
		{
			ans = k;
			return true;
		}
	}
	return false;
}

int main()
{

	scanf("%d%d", &n, &m);

	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (int i = 1; i <= m; i++)
		scanf("%d%d%d", &d[i], &l[i], &r[i]);


	int l = 1, r = m;
	while (l<r)
	{
		int mid = (l + r) / 2;
		if (check(mid))r = mid;
		else
			l = mid + 1;
	}

	if (!ans)
		printf("0");
	else
		printf("-1\n%d", ans);
	return 0;
}

发布了41 篇原创文章 · 获赞 2 · 访问量 1253

猜你喜欢

转载自blog.csdn.net/qq_41418281/article/details/100120418
今日推荐