文章目录
D. Program
传送门
题意:给一个长度为
n
n
n的’+’,’-‘序列,‘+’代表加1,’-'号代表减1 ,和
q
q
q次询问,每次询问,输入
l
,
r
l,r
l,r表示删除
[
l
,
r
]
[l,r]
[l,r]序列,
[
1
,
l
−
1
]
[1,l-1]
[1,l−1]和
[
r
+
1
,
n
]
[r+1,n]
[r+1,n]按原顺序拼接,问删除后的序列出现了多少数字?
思路:求当前序列出现多少个数字,因为只有加一减一,数的变化是连续的,所以出现数字=最大值-最小值+1,所以我们只要求出当前序列的最大最小值,删除 [ l , r ] [l,r] [l,r]对前 [ 1 , l − 1 ] [1,l-1] [1,l−1]的最大最小值无影响,对 [ r + 1 , n ] [r+1,n] [r+1,n]的最大最小值需要减去 [ l , r ] [l,r] [l,r]的和。
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;
const int N=2e5+10;
int n,q;
char s[N];
int a[N];
int minl[N],maxl[N]; //minl[i]表示[1,i]中a[i]的最小值
int minr[N],maxr[N]; //maxr[i]表示[i+1,n]中a[i]的最大值
void solve()
{
cin>>n>>q>>s+1;
rep(i,1,n)
{
if(s[i]=='+') a[i]=1;
else a[i]=-1;
}
rep(i,1,n) a[i]+=a[i-1]; //求a[i]的前缀和
rep(i,0,n+1)
{
minl[i]=minr[i]=1e9;
maxl[i]=maxr[i]=-1e9;
}
rep(i,1,n)
{
minl[i]=min(minl[i-1],a[i]);
maxl[i]=max(maxl[i-1],a[i]);
}
per(i,n,1) // 倒序求minr[i],maxr[i]
{
minr[i]=min(minr[i+1],a[i]);
maxr[i]=max(maxr[i+1],a[i]);
}
while(q--)
{
int l,r;
cin>>l>>r;
int minv=0,maxv=0; // [1,l-1]和[r+1,n]中的最小值和最大值
if(l>1) //删除[l,r]对l-1的minl,maxl无影响
{
minv=min(minv,minl[l-1]);
maxv=max(maxv,maxl[l-1]);
}
int sum=a[r]-a[l-1]; //求[l,r]中a[i]的和
if(r<n) //删除[l,r]使r+1的minl,maxl减掉sum
{
minv=min(minv,minr[r+1]-sum);
maxv=max(maxv,maxr[r+1]-sum);
}
cout<<maxv-minv+1<<endl;
}
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0);
int _; cin>>_;
while(_--) solve();
return 0;
}