CF1710B Rain 差分+数学分析
题意简述
给出若干个雨中心 与降雨强度 。
对于每场雨 ,对位置 积水的贡献为
任意一个位置积水大于 就会发洪水,问抹去一场降雨,是否不会发洪水。
问题分析
首先,发洪水的地方一定是某个降雨中心。
本质上,每个位置的积水深度是若干个绝对值函数 叠加的结果。容易知道类似的函数在零点取到极值。
可以通过离散化,将值域缩小到 。
维护两个差分数组:斜率和截距,可以算出每个位置的积水量。
如果一个降水中心 ,原来的积水量为 ,去掉降雨 后积水量不超过 ,则有 。
这里不处理 的原因是:若题目中 的式子在这里取零,即有 ,与 矛盾,故题目中的式子在这里 。
拆开绝对值有:
移项,有
维护 和 的最大值即可。
一个注意点:多测清空时,差分数组要清到 的位置。
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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!