Codeforces 1548E Gregor and the Two Painters

Posted by Yaak on Sat, 04 Dec 2021 22:57:40 +0100

Title Link

Codeforces 1548E Gregor and the Two Painters

General idea of the topic

There are two sequences \ (\ {a \} \) and \ (\ {B \} \) with lengths of \ (n \) and \ (m \) respectively, so as to construct the grid of \ (n\times m \). The weight at \ ((i,j) \) is \ (a_i+b_j \), which is called grid \ ((i,j) \) is bad if the weight of grid \ (\ leq X \). Find the number of connected blocks of the bad lattice in the graph.

\(1\leq n,m,a_i,b_i,X\leq 2\times 10^5\)

thinking

Interesting questions with strong thinking.

\The grid of (2e5\times2e5 \) is very large. At the same time, it is easy to construct the data with the answer \ (\ frac{nm}{4} \) and it is impossible to maintain it with things such as search sets. Therefore, we bumped around to study monotonicity and inclusion. We couldn't think of such an idea after we were forced to look at Hint. We tried to select a marker point for each connected block, In this way, you only need to quickly count the number of marked points.

It is difficult to select the marked points through the shape attributes, because the shape of the connected block is almost arbitrary, it is difficult to quickly determine whether the points meet the requirements. Therefore, it is easy to think of picking the point with the smallest weight through the point's own attributes. For the smallest point, other parts of the connected block are larger than it, but the bad grid is obviously larger than it. Then we frame a rectangle around the connected block (circumscribed). It can be proved that the marked point is the smallest point in the rectangle. This proposition is equivalent to that there will be no other bad grid connected blocks in the rectangle, but note that for two adjacent rows in the grid, The bad lattice set they have must be the inclusion relationship (monotonicity), and if there are other connected blocks, it will violate this property, resulting in the situation that there is no connection here, but the place that should be included is connected instead.

Thus, the \ (a_i \) and \ (b_i \) of the marked point \ ((i,j) \) are the minimum values in the corresponding interval of the rectangle. Therefore, to determine whether a point is a marked point, we only need to look at whether the first lattice with smaller weight is in a connected block in the horizontal and vertical directions, and then according to the inclusion between rows (and columns), It can be simplified as: whether there is a grid with weight \ (> x \) on the line between smaller grids.

With this nature, we can start statistics. For the \ (\ {a \} \) sequence, the monotone stack is used to maintain the position of the first \ (< a_i \) encountered by \ (a_i \) from left to right, which is recorded as \ (l_i,r_i \), and then recorded as \ (na_i=\min(\max_{i\in[l_i,i-1]}\{a_i\},\max_{i\in[i+1,r_i]}\{a_i \}) \), indicating that if the point in line \ (I \) is to become a non marked point, the connected block needs to contain the line of \ (a_j=na_i \), \ (na_i \) It can be maintained in the monotonous stack, and \ (nb_i \) can be processed similarly. Now you can get that a point is a marker point if and only if:

  • \(a_i+b_j\leq X\)
  • \(a_i+nb_j>X\)
  • \(na_i+b_j>X\)

This is a concise partial order problem! For the latter two restrictions, just require the smaller \ (> x \) in \ (a_i+nb_i,\;na_i+b_i \), move the item and check the corresponding formula with the larger \ (na_i-a_i,\;nb_i-b_i \). Therefore, we maintain two tree arrays \ (T_a,T_b \), and process the binary of \ ((na_i-a_i,a_i) \) and \ ((nb_i-b_i,b_i) \) from large to small. If it is \ ((na_i-a_i,a_i) \), add the weight of \ ((X-na_i,X-a_i] \) in \ (T_b \), and then add \ (1 \) to the position of \ (a_i \) in \ (T_a \), which is similar to \ ((nb_i-b_i,b_i)).

Time complexity \ (O(n\log n) \)

Code

#include<iostream>
#include<stack>
#include<algorithm>
#include<vector>
#define rep(i,a,b) for(int i = (a); i <= (b); i++)
#define per(i,b,a) for(int i = (b); i >= (a); i--)
#define N 200021
#define PII pair<int, int>
#define PIP pair<int, PII>
#define fr first
#define sc second
#define lowbit(x) (x&-x)
#define ll long long
#define Inf 0x3f3f3f3f
using namespace std;

int n, m, x;
int a[N], b[N];
int l[N], r[N], na[N], nb[N];
stack<PII> s;
vector<PIP> vec;

struct Fenwick{
    int t[N];
    void update(int pos, int k){
        while(pos < N) t[pos] += k, pos += lowbit(pos);
    }
    int get(int pos){
        int ret = 0;
        while(pos) ret += t[pos], pos -= lowbit(pos);
        return ret;
    }
} T[2];

void prework(int n, int *a, int *na){
    a[0] = a[n+1] = x+1;
    s.push({0, x+1});
    rep(i,1,n){
        int mx = a[i];
        while(!s.empty() && a[s.top().fr] >= a[i]) mx = max(mx, s.top().sc), s.pop();
        l[i] = mx, s.push({i, mx});
    }
    while(!s.empty()) s.pop();
    s.push({n+1, x+1});
    per(i,n,1){
        int mx = a[i];
        while(!s.empty() && a[s.top().fr] > a[i]) mx = max(mx, s.top().sc), s.pop();
        r[i] = mx, s.push({i, mx});
    }
    while(!s.empty()) s.pop();
    rep(i,1,n) na[i] = min(l[i], r[i]);
}

int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m>>x;
    rep(i,1,n) cin>>a[i];
    rep(i,1,m) cin>>b[i];

    prework(n, a, na), prework(m, b, nb);
    ll ans = 0;
    rep(i,1,n) vec.push_back({na[i]-a[i], {a[i], 0}});
    rep(i,1,m) vec.push_back({nb[i]-b[i], {b[i], 1}});
    sort(vec.begin(), vec.end());
    reverse(vec.begin(), vec.end());
    for(PIP p : vec){
        ans += T[p.sc.sc^1].get(max(x-p.sc.fr, 0)) - T[p.sc.sc^1].get(max(x - (p.fr+p.sc.fr), 0));
        T[p.sc.sc].update(p.sc.fr, 1);
    }
    cout<< ans <<endl;
    return 0;
}

Topics: data structure CodeForces