cf1473 D. Program(思维)
题意:
初值 x 为 0,给一段 -+--+--+ 命令,+ 表示当前值+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;
}

浙公网安备 33010602011771号