ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1710B Rain 差分+数学分析

2022-08-08 05:30:08  阅读:128  来源: 互联网

标签:le int max CF1710B 差分 mid ch Rain 积水


题意简述

给出若干个雨中心 \(x_i\) 与降雨强度 \(p_i\)。

对于每场雨 \(x,p\),对位置 \(i\) 积水的贡献为 \(\max \{0, |x-i|+p \}\)

任意一个位置积水大于 \(m\) 就会发洪水,问抹去一场降雨,是否不会发洪水。


问题分析

首先,发洪水的地方一定是某个降雨中心。

本质上,每个位置的积水深度是若干个绝对值函数 \(f(x)=|x-x_i|\) 叠加的结果。容易知道类似的函数在零点取到极值。

可以通过离散化,将值域缩小到 \(n\)。

维护两个差分数组:斜率和截距,可以算出每个位置的积水量。

如果一个降水中心 \(i\),原来的积水量为 \(R_i>m\),去掉降雨 \(k\) 后积水量不超过 \(m\),则有 \(R_i - |x_j-x_i| - p_j \le m\)。

这里不处理 \(\max\) 的原因是:若题目中 \(\max\) 的式子在这里取零,即有 \(R_i \le m\),与 \(R_i > m\) 矛盾,故题目中的式子在这里 \(>0\)。

拆开绝对值有:

\[\begin{cases} R_i - x_j + x_i - p_j \le m \\ R_i - x_i + x_j - p_j \le m \end{cases} \]

移项,有

\[\begin{cases} R_i + x_i \le x_j + p_j +m \\ R_i - x_i \le -x_j + p_j + m \end{cases} \]

维护 \(R_i+x_i\) 和 \(R_i-x_i\) 的最大值即可。

一个注意点:多测清空时,差分数组要清到 \(n+1\) 的位置。


Codes

#include<bits/stdc++.h>
using namespace std;

#define int long long
typedef long long LL;

template < typename Tp >
void read(Tp &x) {
	x = 0; int fh = 1; char ch = 1;
	while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
	if(ch == '-') fh = -1, ch = getchar();
	while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	x *= fh;
}

const int maxn = 200000 + 7;

int T, n, m;
struct rain {
	int x, p, id;
	bool ans;
}a[maxn];

void Init(void) {
	read(T);
}

bool cmp(rain a, rain b) {
	return a.x == b.x ? a.p < b.p : a.x < b.x;
}

bool comp(rain a, rain b) {
	return a.id < b.id;
}

int sk[maxn], sb[maxn], r[maxn];

int lfind(rain t) {
	int l = 1, r = n, mid, res = n;
	while(l <= r) {
		mid = ((l + r) >> 1);
		if(a[mid].x >= t.x - t.p) res = mid, r = mid - 1;
		else l = mid + 1;
	}
	return res;
}

int rfind(rain t) {
	int l = 1, r = n, mid, res = 1;
	while(l <= r) {
		mid = ((l + r) >> 1);
		if(a[mid].x <= t.x + t.p) res = mid, l = mid + 1;
		else r = mid - 1;
	}
	return res;
}

void Work(void) {
	while(T--) {
		for(int i = 1; i <= n + 1; i++) {
			sb[i] = sk[i] = r[i] = 0;
//			a[i].x = a[i].p = a[i].id = a[i].ans = 0;
		}
		read(n); read(m);
		for(int i = 1; i <= n; i++) {
			read(a[i].x); read(a[i].p);
			a[i].id = i;
		}
		sort(a + 1, a + n + 1, cmp);
		for(int i = 1; i <= n; i++) {
			int lb = lfind(a[i]), rb = rfind(a[i]);
			sk[lb]++, sk[i + 1] -= 2, sk[rb + 1]++;
			sb[lb] += a[i].p - a[i].x;
			sb[i + 1] -= a[i].p - a[i].x;
			sb[i + 1] += a[i].p + a[i].x;
			sb[rb + 1] -= a[i].p + a[i].x;
		}
		for(int i = 1; i <= n; i++) {
			sk[i] += sk[i - 1];
			sb[i] += sb[i - 1];
			r[i] = sb[i] + sk[i] * a[i].x;
//			cout << r[i] << " ";
		}
		int mx1 = -0x3f3f3f3f3f3f3f3fll, mx2 = -0x3f3f3f3f3f3f3f3fll;
		for(int i = 1; i <= n; i++) {
			if(r[i] > m) mx1 = max(mx1, r[i] - a[i].x);
			if(r[i] > m) mx2 = max(mx2, r[i] + a[i].x);
		}
		for(int i = 1; i <= n; i++) {
			if(a[i].p - a[i].x + m >= mx1 && a[i].x + a[i].p + m >= mx2) a[i].ans = true;
			else a[i].ans = false;
		}
		sort(a + 1, a + n + 1, comp);
		for(int i = 1; i <= n; i++) printf("%d", a[i].ans);
		puts("");
	}
}

signed main(void) {
	Init();
	Work();
	return 0;
}

标签:le,int,max,CF1710B,差分,mid,ch,Rain,积水
来源: https://www.cnblogs.com/liubainian/p/16560444.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有