cf1473 D. Program(思维)

题意:

初值 x0,给一段 -+--+--+ 命令,+ 表示当前值+1,- 表示当前值-1。有m个询问,每个询问 l r 表示屏蔽第 l 到第 r 个命令,剩下的命令按原顺序执行。对每个询问,输出命令执行的过程中出现的不同值的数量,初值0也要算。

思路:

x 的变化是连续的,若变化过程中出现的最大值为 maxx,最小值为 minn,中间不同的取值数 maxx-minn+1 就是答案。对 r 之后的最值,只需要消除 [l,r] 的影响,即减去 a[r]-a[l-1]

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
//+-序列的前缀和, [0,i]中的前缀和最值, [i,r]中的前缀和最值
int a[N], minl[N], minr[N], maxl[N], maxr[N];
signed main()
{
    int T; cin >> T; while(T--)
    {
        int n, m; scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++)
        {
            char c; scanf(" %c", &c);
            if(c == '+') a[i] = a[i-1] + 1;
            else a[i] = a[i-1] - 1;
        }

        minl[0] = 0, maxl[0] = 0;
        for(int i = 1; i <= n; i++)
            minl[i] = min(minl[i-1], a[i]),
            maxl[i] = max(maxl[i-1], a[i]);
        minr[n+1] = N, maxr[n+1] = -N;
        for(int i = n; i >= 1; i--)
            minr[i] = min(minr[i+1], a[i]),
            maxr[i] = max(maxr[i+1], a[i]);

        while(m--)
        {
            int l, r; scanf("%d%d", &l, &r);
            int d = a[r] - a[l-1];
            int maxx = max(maxl[l-1], maxr[r+1] - d);
            int minn = min(minl[l-1], minr[r+1] - d);
            printf("%d\n", maxx - minn + 1);
        }
    }

    return 0;
}

posted @ 2021-12-16 16:43  Bellala  阅读(30)  评论(0)    收藏  举报