CF1710B Rain 差分+map
考虑某次i的降雨(x[i], p[i]),针对位置pos研究消去i降雨的影响。
假设pos处的n次总降雨量为sum,且pos>x[i],则降雨在pos处为斜率-1的线段,pos处若合法则需满足sum - (p[i] - (pos - x[i])) <= m,也即p[i] + x[i] >= sum + pos - m;同理可得pos < x[i]时,需满足p[i] - x[i] >= sum - pos - m。
使用map进行差分记录,极值只可能在降雨处、降雨影响的两个端点,共三个位置出现。
需要在差分过程中计算:
1.pos处的总降水量
2.最大值0更新(sum + pos - m)
3.最大值1更新(sum - pos - m)
最后遍历所有的降雨地点,查看(x[i], p[i])是否满足上述区间,满足则表示删去时全体小于等于m,合法。
1 #include<iostream>
2 #include<algorithm>
3 #include<map>
4 #define ll long long
5 using namespace std;
6 const int N = 2E5 + 10;
7 const int INF = 0x3f3f3f3f;
8 int n, m;
9 ll x[N], p[N];
10 map<ll, ll> mp;
11
12 int main(){
13 ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
14 int t; cin >> t;
15 while(t--)
16 {
17 cin >> n >> m;
18 mp.clear();
19 for(int i = 1 ; i <= n ; i++) {
20 cin >> x[i] >> p[i];
21 mp[x[i] - p[i] + 1] += 1;
22 mp[x[i] + 1] -= 2;
23 mp[x[i] + p[i] + 1] += 1;
24 // 潜在极值点:x[i]、x[i] - p[i]、x[i] + p[i] --> 归并为mp中的x.first - 1
25 }
26 int last = -INF;
27 ll m0 = -INF, m1 = -INF;
28 ll step = 0, s = 0;
29 for(auto x : mp) {
30 s += (x.first - last) * step;
31 step += x.second;
32 if(s > m) { // 出现大于m的极值点
33 m0 = max(m0, s - (x.first - 1));
34 m1 = max(m1, s + (x.first - 1));
35 }
36 last = x.first;
37 }
38 for(int i = 1 ; i <= n ; i++) {
39 if(x[i] + p[i] >= m1 - m && p[i] - x[i] >= m0 - m) {
40 cout << 1;
41 }else {
42 cout << 0;
43 }
44 }
45 cout << endl;
46 }
47
48
49
50 return 0;
51 }