Educational Codeforces Round 102 D. Program (line segment tree)

D. Program

Question portal:

D. Program

Ideas:

If the maximum number of passes in the process is required, then only the maximum value of the interval-the minimum value of the interval +1 is required. Obviously, we can use the line segment tree to maintain the maximum and minimum values ​​of the interval, but there is also how to delete the interval in the question.
1. If the deleted interval is the second half, then just query the maximum and minimum values ​​of the first half of the interval.
2. If the deleted interval is the first half, then after searching the maximum and minimum of the second half of the interval, Also subtract it from the sum of the deleted interval.
3. If the deleted interval is in the middle, then the judgment of the first step and the second step must be performed at the same time.
But it should be noted that in either case, you have to consider the relationship between the maximum, minimum and 0, because it is 0 at the beginning.

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;
}

Guess you like

Origin blog.csdn.net/Stevenwuxu/article/details/112932624