codeforces1473D Program (line segment tree or linear dp optimization)

Portal
Solution: Think about it, you can know that it can be performed continuously in an interval + / − +/-+ / − After the operation,xx inthis intervalThe change of x is continuous, that is, it is enough to find the maximum and minimum values ​​in the change. Finally, it is to maintain the maximum and minimum values ​​of the interval. For skipping an operation in the middle, the impact on the latter is nothing more than subtracting this period.xxThe influence of x is nothing.

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, m, x, y, a[N];
string s;
struct node{
    
    
    int l, r, mx, mn;
};
node tree[N << 2];
void build(int p, int l, int r)
{
    
    
    tree[p].l = l; tree[p].r = r;
    if (l == r) {
    
    
        tree[p].mx = tree[p].mn = a[l];
        return ;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    tree[p].mx = max(tree[p << 1].mx, tree[p << 1 | 1].mx);
    tree[p].mn = min(tree[p << 1].mn, tree[p << 1 | 1].mn);
}
pair<int, int> ask(int p, int l, int r)
{
    
    
    if (tree[p].l >= l && tree[p].r <= r) {
    
    
        return {
    
    tree[p].mx, tree[p].mn};
    }
    int mid = (tree[p].l + tree[p].r) >> 1;
    if (r <= mid) {
    
    
        return ask(p << 1, l, r);
    } else if (l > mid) {
    
    
        return ask(p << 1 | 1, l, r);
    } else {
    
    
        auto tl = ask(p << 1, l, mid), tr = ask(p << 1 | 1, mid + 1, r);
        return {
    
    max(tl.first, tr.first), min(tl.second, tr.second)};
    }
}
int main()
{
    
    
    int T;
    cin >> T;
    while (T--) {
    
    
        cin >> n >> m >> s;
        for (int i = 0; i < n; i++) {
    
    
            a[i+2] = a[i+1] + (s[i] == '+' ? 1 : -1);
        }
        n += 2; a[n] = a[n - 1];
        build(1, 1, n);
        for (int i = 0; i < m; i++) {
    
    
            cin >> x >> y;
            x += 1; y += 1;
            int t = a[y] - a[x - 1];
            auto l = ask(1, 1, x - 1), r = ask(1, y, n);
            r.first -= t; r.second -= t;
            cout << max(l.first, r.first) - min(l.second, r.second) + 1 << endl;
        }
    }
    return 0;
}

My approach as above is O (nlogn) O(nlogn)O ( n l o g n ) level, the official problem isO (n) O(n)O ( n ) level
thinking is still the same, but maintenance has to be thought about, consider usingpr [i] pr[i]p r [ i ] means that theiiis currently reachedWhat is the number in the i digit, prl [i], prr [i] prl[i], prr[i]prl[i]prr[i]为前 i i The length of i is the smallest, the largest, and the maintenance is very simple.
prl [i] = min (prl [i − 1], pr [i] + d) prr [i] = max (prr [i − 1], pr [i ] + d) prl[i]=min(prl[i-1],pr[i]+d)\\ prr[i]=max(prr[i-1],pr[i]+d)p r l [ i ]=m i n ( p r l [ i1],p r [ i ]+d)prr[i]=max(prr[i1],p r [ i ]+d )
But the suffix is ​​a bit tricky, consider such a thing, if you already knowsul[i] sul[i]s u l [ i ] means from theiithe smallest starting from i , then thei − 1 i-1iFor 1 digit, it must besul [i − 1] = sul [i] + d sul[i-1]=sul[i]+dsul[i1]=sul[i]+d , if it is a positive number, it is1 11 , then change to0 00 is enough. If it is not for this formula, then it can only be bigger instead of the smallest, and the same is true for the largest.
Maintainpr [l − 1] pr[l-1]directly when maintaining the answer at the endp r [ l1 ] value

#include <bits/stdc++.h>
using namespace std;
int n, m, l, r;
string s;
int main()
{
    
    
    int T;
    cin >> T;
    while (T--) {
    
    
        cin >> n >> m >>s;
        vector<int> sul(1, 0), sur(1, 0), prl(1, 0), prr(1, 0), pr(1, 0);
        for (int i = n - 1; i >= 0; i--) {
    
    
            int d = s[i] == '+' ? 1 : -1;
            sul.emplace_back(min(0, sul.back() + d));
            sur.emplace_back(max(0, sur.back() + d));
        }
        reverse(sul.begin(), sul.end());
        reverse(sur.begin(), sur.end());
        for (int i = 0; i < n; i++) {
    
    
            int d = s[i] == '+' ? 1 : -1;
            pr.emplace_back(pr.back() + d);
            prl.emplace_back(min(prl.back(), pr.back()));
            prr.emplace_back(max(prr.back(), pr.back()));
        }
        for (int i = 0; i < m; i++) {
    
    
            cin >> l >> r;
            l--;
            int l1 = prl[l], r1 = prr[l];
            int l2 = sul[r] + pr[l], r2 = sur[r] + pr[l];
            cout << max(r1, r2) - min(l1, l2) + 1 << endl;
        }
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/zhouzi2018/article/details/112743371