CF1710B Rain 差分+map

发布时间 2023-07-04 10:10:45作者: LegendN

考虑某次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 }