gym 101879G Running a penitentiary

题目链接:http://codeforces.com/gym/101879/problem/G

题意:有n个警察,第i个警察看管监狱的区间是【Li,Ri】。
有两种操作:C i l r :把第i个警察的区间变为【l,r】。
?l r :询问从第l个警察到第r个警察共同看管的区间长度是多少

我的思路:以警察来建线段树,每次维护一个区间里最大的l和最小的r,这样很容易得到这个区间里的警察的公共区间的长度就是r-l+1。最后就变成了单点更新+区间询问的线段树。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+3;
#define lson rt<<1
#define rson rt<<1|1
ll xl[maxn],xr[maxn];
struct node//个人觉得用结构体会简便一点
{
    ll l,r,len;
}tree[maxn<<2];
int cnt;

void bulid(ll rt,ll l,ll r)
{
    if(l==r)
    {
        tree[rt].l=xl[++cnt];
        tree[rt].r=xr[cnt];
        tree[rt].len=xr[cnt]-xl[cnt]+1;
        return;
    }
    ll mid=(l+r)>>1;
    bulid(lson,l,mid);
    bulid(rson,mid+1,r);
    tree[rt].l=max(tree[lson].l,tree[rson].l);//向上更新
    tree[rt].r=min(tree[lson].r,tree[rson].r);
    tree[rt].len=tree[rt].r-tree[rt].l+1;
}

void updata(ll rt,ll l,ll r,ll x,ll newl,ll newr)
{
    if(l==x&&r==x)
    {
        tree[rt].l=newl;
        tree[rt].r=newr;
        tree[rt].len=tree[rt].r-tree[rt].l+1;
        return;
    }
    ll mid=(l+r)>>1;
    if(x<=mid)updata(lson,l,mid,x,newl,newr);
    else updata(rson,mid+1,r,x,newl,newr);
    tree[rt].l=max(tree[lson].l,tree[rson].l);//向上更新
    tree[rt].r=min(tree[lson].r,tree[rson].r);
    tree[rt].len=tree[rt].r-tree[rt].l+1;
}

node query(ll rt,ll l,ll r,ll x,ll y)
{
    if(l>=x&&r<=y)
    {
        return tree[rt];
    }
    ll mid=(l+r)>>1;
    node a,b,c;
    bool ff=false;
    if(y<=mid)a=query(lson,l,mid,x,y);
    else if(x>=mid+1)a=query(rson,mid+1,r,x,y);
    else a=query(lson,l,mid,x,mid),b=query(rson,mid+1,r,mid+1,y),ff=true;
    if(ff)//如果是左右两个子树都有的话,就要重新更新最大的l和最小的r
    {
        c.l=max(a.l,b.l);
        c.r=min(a.r,b.r);
        c.len=c.r-c.l+1;
        return c;
    }
    else return a;
}

int main()
{
    int n,q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)scanf("%lld%lld",&xl[i],&xr[i]);
    cnt=0;
    bulid(1,1,n);
    char o[2];
    int tp1,tp2,tp3;
    for(int i=1;i<=q;i++)
    {
        scanf("%s",o);
        if(o[0]=='?')
        {
            scanf("%d%d",&tp1,&tp2);
            node ans=query(1,1,n,tp1,tp2);
            printf("%lld\n",ans.len>=0?ans.len:0);//如果一个区间的长度是负的,也就是没有公共区间
        }
        else
        {
            scanf("%d%d%d",&tp1,&tp2,&tp3);
            updata(1,1,n,tp1,tp2,tp3);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40942372/article/details/82828780