BZOJ 3693. 圆桌会议 题解

首先,对于圆环问题,我们肯定要复制加倍转成区间。

然后根据 Hall 定理可得:\(\sum^{j}_{k=i}a_k \le l+i-r_j+1\),即 \(\sum^{j}_{k=i}a_k+l_i-1 \le r_j\)

考虑线段树维护 \(\sum^{j}_{k=i}a_k+l_i-1\),我们按右端点排序,离散化,然后依次查询。

对于修改,只有包含询问的才有 \(a_i\) 的贡献,所以 \([1,l_i]\) 修改。

对于查询,只有询问的 \(l\) 右边一直到 \(r\)\(a\) 才会有贡献,维护最大值。

//bzoj#3693. 圆桌会议
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
/***********Basic Defination***********/
#define int long long
const int MAXN=200005;
struct Attendee
{
    int l,r,a;
}s[MAXN];
int b[MAXN<<1],cnt,n,m;
bool operator <(Attendee x,Attendee y)
{
    return x.r<y.r;
}
/***********Segment Tree***********/
struct Segt
{
    int val,lazy;
}tr[MAXN*6];
void pushup(int p)
{
    tr[p].val=max(tr[p<<1].val,tr[p<<1|1].val);
    return;
}
void build(int p,int l,int r)
{
    int mid;
    tr[p].val=tr[p].lazy=0;
    if(l==r)
    {
        tr[p].val=b[l]-1;
        return;
    }
    mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    pushup(p);
    return;
}
void pushdown(int p)
{
    if(tr[p].lazy)
    {
        tr[p<<1].val+=tr[p].lazy;
        tr[p<<1|1].val+=tr[p].lazy;
        tr[p<<1].lazy+=tr[p].lazy;
        tr[p<<1|1].lazy+=tr[p].lazy;
        tr[p].lazy=0;
    }
    return;
}
void update(int p,int l,int r,const int L,const int R,int c)
{
    int mid;
    if(L>r||R<l)
    {
        return;
    }
    if(L<=l&&r<=R)
    {
        tr[p].val+=c;
        tr[p].lazy+=c;
        return;
    }
    pushdown(p);
    mid=(l+r)>>1;
    update(p<<1,l,mid,L,R,c);
    update(p<<1|1,mid+1,r,L,R,c);
    pushup(p);
    return;
}
int query(int p,int l,int r,const int L,const int R)
{
    int mid,res;
    if(L<=l&&r<=R)
    {
        return tr[p].val;
    }
    pushdown(p);
    mid=(l+r)>>1;
    if(R<=mid)
    {
        res=query(p<<1,l,mid,L,R);
    }
    else if(L>mid)
    {
        res=query(p<<1|1,mid+1,r,L,R);
    }
    else 
    {
        res=max(query(p<<1,l,mid,L,R),query(p<<1|1,mid+1,r,L,R));
    }
    pushup(p);
    return res;
}
signed main()
{
    int t,sum,temp;
    bool flag;
    scanf("%lld",&t);
    while(t--)
    {
        sum=0;
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&s[i].l,&s[i].r,&s[i].a);
            s[i].l++;
            s[i].r++;
            sum+=s[i].a;
            if(s[i].r<s[i].l)//把环变成链
            {
                s[i].r+=m;
            }
        }
        temp=n;
        for(int i=1;i<=temp;i++)
        {
            if(s[i].r>m)
            {
                continue;
            }
            s[++n]=s[i];
            s[n].l+=m;
            s[n].r+=m;
        }
        if(sum>m)
        {
            printf("No\n");
            continue;
        }
        cnt=0;
        for(int i=1;i<=n;i++)//离散化
        {
            b[++cnt]=s[i].l;
            b[++cnt]=s[i].r;
        }
        sort(b+1,b+cnt+1);
        sort(s+1,s+n+1);
        temp=cnt;
        for(int i=1;i<=n;i++)
        {
            s[i].l=lower_bound(b+1,b+temp+1,s[i].l)-b;
            s[i].r=lower_bound(b+1,b+temp+1,s[i].r)-b;
        }
        build(1,1,n<<1);
        flag=true;
        for(int i=1;i<=n;i++)
        {
            update(1,1,n<<1,1,s[i].l,s[i].a);
            if(query(1ll,1,n<<1,max(1ll,s[i].r-m+1),s[i].r)>b[s[i].r])
            {
                flag=false;
                break;
            }
        }
        printf(flag?"Yes\n":"No\n");
    }
    return 0;
}
/*
 * HydroOJ-BZOJ
 * https://hydro.ac/d/bzoj/p/3693
 * C++17 -O0
 * 2022.10.11
 */
posted @ 2022-10-11 10:48  Day_Dreamer_D  阅读(182)  评论(0)    收藏  举报