传送门
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
",ans);
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!