Running a penitentiary(区间交集处理)

原题: https://cn.vjudge.net/problem/Gym-101879G

题意: n段区间,操作一:修改一段区间,操作二:查询下标l~r的区间的交集

解析: 求交集,就是左端点的最右值~右端点的最左值,线段树维护一下区间最值即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define eps 1e-5
const int inf=1e9+7;
const int N=2e5+5;
int minn[N*4],maxn[N*4];
struct node
{
    int l,r;
}a[N];
void pushup(int root)
{
    minn[root]=min(minn[root<<1],minn[root<<1|1]);
    maxn[root]=max(maxn[root<<1],maxn[root<<1|1]);
}
void build(int l,int r,int root)
{
    if(l==r)
    {
        minn[root]=a[l].r;
        maxn[root]=a[l].l;
        return ;
    }
    int mid=l+r>>1;
    build(l,mid,root<<1);
    build(mid+1,r,root<<1|1);
    pushup(root);
}
void update(int l,int r,int root,int pos,int ql,int qr)
{
    if(l==r)
    {
        maxn[root]=ql;
        minn[root]=qr;
        return ;
    }
    int mid=l+r>>1;
    if(mid>=pos)
        update(l,mid,root<<1,pos,ql,qr);
    else
        update(mid+1,r,root<<1|1,pos,ql,qr);
    pushup(root);
}
int qmin(int l,int r,int root,int ql,int qr)
{
    if(l>=ql&&r<=qr)
        return minn[root];
    int ans=inf;
    int mid=l+r>>1;
    if(mid>=ql)
        ans=qmin(l,mid,root<<1,ql,qr);
    if(mid<qr)
        ans=min(ans,qmin(mid+1,r,root<<1|1,ql,qr));
    return ans;
}
int qmax(int l,int r,int root,int ql,int qr)
{
    if(l>=ql&&r<=qr)
        return maxn[root];
    int ans=-inf;
    int mid=l+r>>1;
    if(mid>=ql)
        ans=qmax(l,mid,root<<1,ql,qr);
    if(mid<qr)
        ans=max(ans,qmax(mid+1,r,root<<1|1,ql,qr));
    return ans;
}
int main()
{
    for(int i=0;i<N*4;i++)
        minn[i]=inf,maxn[i]=-inf;
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].l,&a[i].r);
    build(1,n,1);
    char s[10];
    int pos,l,r;
    while(m--)
    {
        scanf("%s",s);
        if(s[0]=='C')
        {
            scanf("%d%d%d",&pos,&l,&r);
            update(1,n,1,pos,l,r);
        }
        else
        {
            scanf("%d%d",&l,&r);
            int Min=qmin(1,n,1,l,r);
            int Max=qmax(1,n,1,l,r);
            if(Min>=Max)
                printf("%d\n",Min-Max+1);
            else
                printf("0\n");
        }
    }
    return 0;
}
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页