CF1710B Rain 差分+数学分析

题意简述

给出若干个雨中心 xi 与降雨强度 pi

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

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


问题分析

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

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

可以通过离散化,将值域缩小到 n

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

如果一个降水中心 i,原来的积水量为 Ri>m,去掉降雨 k 后积水量不超过 m,则有 Ri|xjxi|pjm

这里不处理 max 的原因是:若题目中 max 的式子在这里取零,即有 Rim,与 Ri>m 矛盾,故题目中的式子在这里 >0

拆开绝对值有:

{Rixj+xipjmRixi+xjpjm

移项,有

{Ri+xixj+pj+mRixixj+pj+m

维护 Ri+xiRixi 的最大值即可。

一个注意点:多测清空时,差分数组要清到 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;
}
posted @   览遍千秋  阅读(125)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示