D. Program
题目传送门:
思路:
如果要求过程中最多经过多少个数,那么只要求得 区间最大值 - 区间最小+1 即可。区间的最大值和最小值,我们显然都可以用线段树维护,但是题目中还有一个区间的删除操作该怎么进行呢。
1.如果删除的区间是后半段,那么只要查询前半段区间的最大值和最小值即可
2.如果删除的区间是前半段,那么在查寻后半段区间的最大值和最小值之后,还要将其减去删去区间的和。
3.如果删去的区间位于中间,那么就要同时进行第一步和第二步的判断。
但需要注意的是,不管是哪种情况,你都得考虑最大值,最小值和0的关系,因为最开始为0。
AC Code
/*
1.删前半段,那么要查询后半段的最大值和最小值
2.删狐半段,那么要查询前半段的最大值和最小值
3.删中间,那么要同时查询前半段和后半段,并且大的取大,小的取小
需要注意的是,不管是哪种情况,都需要注意和0的关系
*/
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],sum[N];
struct node
{
int k,l,r;
int minn,maxn;
}tr[N*4];
void pushup(int k)
{
tr[k].maxn=max(tr[k<<1].maxn,tr[k<<1|1].maxn);
tr[k].minn=min(tr[k<<1].minn,tr[k<<1|1].minn);
}
void build(int k,int l,int r)//建树
{
tr[k].l=l,tr[k].r=r;
if(l==r)
{
tr[k].maxn=tr[k].minn=sum[l];
return ;
}
int mid=(l+r)/2;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
int query_min(int k,int l,int r)//查询区间最小值
{
if(tr[k].l>=l&&tr[k].r<=r)
return tr[k].minn;
int mid=(tr[k].l+tr[k].r)/2;
int ans=4e5;
if(l<=mid) ans=query_min(k<<1,l,r);
if(r>mid) ans=min(ans,query_min(k<<1|1,l,r));
return ans;
}
int query_max(int k,int l,int r)//查询区间最大值
{
if(tr[k].l>=l&&tr[k].r<=r)
return tr[k].maxn;
int mid=(tr[k].l+tr[k].r)/2;
int ans=-4e5;
if(l<=mid) ans=query_max(k<<1,l,r);
if(r>mid) ans=max(ans,query_max(k<<1|1,l,r));
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
string str;
cin>>str;
for(int i=0;i<n;i++)
{
if(str[i]=='-') a[i+1]=-1;
else a[i+1]=1;
}
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
build(1,1,n);
while(m--)
{
int x,y;
int res;
scanf("%d%d",&x,&y);
if(x==1&&y==n) printf("1\n");
else if(x==1) //删去前半段
{
int maxn=query_max(1,y+1,n);
int minn=query_min(1,y+1,n);
maxn=maxn-sum[y];
minn=minn-sum[y];
res=maxn-minn+1;
if(minn>0||maxn<0) res++;
printf("%d\n",res);
}
else if(y==n) //删去后半段
{
int maxn=query_max(1,1,x-1);
int minn=query_min(1,1,x-1);
res=maxn-minn+1;
if(minn>0||maxn<0) res++;
printf("%d\n",res);
}
else //删去中间
{
int maxn1=query_max(1,1,x-1);
int minn1=query_min(1,1,x-1);
int maxn2=query_max(1,y+1,n);
int minn2=query_min(1,y+1,n);
maxn2=maxn2-(sum[y]-sum[x-1]);
minn2=minn2-(sum[y]-sum[x-1]);
int maxn=max(maxn1,maxn2);
int minn=min(minn1,minn2);
res=maxn-minn+1;
if(minn>0||maxn<0) res++;
printf("%d\n",res);
}
}
}
//system("pause");
return 0;
}