[300iq Contest 1-D]Dates

传送门

Description

每个妹子匹配一个时间区间,每个时间最多选择\(a_i\)个妹子,每个妹子有一个快乐值,最大化总快乐值

Solution

贪心,从大往小取,能取则取
判断是否可以有完美匹配:根据Hall定理,只要满足任意一个区间的匹配集合大于区间大小即可
可以等价的判断匹配的区间是否大于区间大小,因为不合法的情况必然包含在一个区间中
可以用线段树区间加减(用于维护下标的变化)+求max和min来判断合法性


Code 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define reg register
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
#define ls x<<1
#define rs x<<1|1
const int MN=3e5+5,inf=0x3f3f3f3f;
ll N,M,a[MN],g[MN],L[MN],R[MN],id[MN];
ll ans;
bool cmp(int x,int y){return g[x]>g[y];}
struct node{int ma,mi,val,p,lz;}T[MN<<2];
void up(int x)
{
    T[x].ma=max(T[ls].ma,T[rs].ma);
    T[x].mi=min(T[ls].mi,T[rs].mi);
    T[x].val=max(T[ls].val,T[rs].val);
    T[x].val=max(T[x].val,T[rs].ma-T[ls].mi);
}
void upd(int x,int v){T[x].ma+=v;T[x].mi+=v;T[x].p+=v;T[x].lz+=v;}
void down(int x){if(!T[x].lz)return;upd(ls,T[x].lz);upd(rs,T[x].lz);T[x].lz=0;}
void Build(int x,int l,int r)
{
    if(l==r)
    {
        L[l]=a[read()-1];R[l]=a[read()];g[l]=read(),id[l]=l;
        T[x].ma=-inf,T[x].mi=inf;T[x].val=-2*inf;return;
    }
    int mid=(l+r)>>1;
    Build(ls,l,mid);Build(rs,mid+1,r);up(x);
}

void md1(int x,int l,int r,int a,int v)
{
    if(l==r)
    {
        if(v==1) T[x].val=(T[x].ma=T[x].p-R[l])-(T[x].mi=T[x].p-L[l]);
        else T[x].ma=-inf,T[x].mi=inf,T[x].val=-2*inf;
        return;
    }
    int mid=(l+r)>>1;down(x);
    a<=mid?md1(ls,l,mid,a,v):md1(rs,mid+1,r,a,v);up(x);
}
void md2(int x,int l,int r,int a,int b,int v)
{
    if(l==a&&r==b){upd(x,v);return;}
    int mid=(l+r)>>1;down(x);
    if(b<=mid)md2(ls,l,mid,a,b,v);
    else if(a>mid)md2(rs,mid+1,r,a,b,v);
    else md2(ls,l,mid,a,mid,v),md2(rs,mid+1,r,mid+1,b,v);up(x);
}
void add(int x,int v){md2(1,1,M,x,M,v);md1(1,1,M,x,v);}

int main()
{
    M=read(),N=read();reg int i;
    for(i=1;i<=N;++i)a[i]=read()+a[i-1];
    Build(1,1,M);std::sort(id+1,id+M+1,cmp);
    for(i=1;i<=M;++i)
    {
        add(id[i],1);
        if(T[1].val<=-1)ans+=g[id[i]];
        else add(id[i],-1);
    }
    return 0*printf("%lld\n",ans);
}


Blog来自PaperCloud,未经允许,请勿转载,TKS!

posted @ 2019-10-31 21:18  PaperCloud  阅读(304)  评论(0编辑  收藏  举报