LOJ3192 「ROI 2019 Day2」课桌

Link
注意到如果一种课桌的合适区间被其它的某种课桌的合适区间完全包含,那么我们就可以把这种课桌去掉。
把剩下来的课桌按左端点升序排序,那么这些课桌的右端点也是递增的。
然后把每个班里的学生按身高升序排序,那么显然相邻的两个同学会坐同一个课桌,这样我们可以把一个班的所有学生分成\(n\)组。
然后我们可以发现所有班的组号相同的组都会做同一张课桌。
可以发现每一个组选择的课桌是单调的,直接分治+决策单调性即可。

#include<cctype>
#include<cstdio>
#include<vector>
#include<numeric>
#include<algorithm>
using i64=long long;
const int N=400007;
char ibuf[1<<23],*iS=ibuf;int m,n,k,tot;i64 now[N],sum[N],ans;std::vector<int>h[N];
struct node{int l,r;}a[N],b[N];
int read(){int x=0;while(isspace(*iS))++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return x;}
void solve(int l,int r,int L,int R)
{
    if(l>r) return ;
    int mid=(l+r)/2,pos=0;i64 mn=1e18;
    for(int i=1;i<=m;++i) now[i+i-1]=h[i][mid*2-2],now[2*i]=h[i][mid*2-1];
    std::sort(now+1,now+m+m+1),std::partial_sum(now+1,now+m+m+1,sum+1);
    for(int i=L;i<=R;++i)
    {
	int pl=std::lower_bound(now+1,now+m+m+1,b[i].l)-now,pr=std::upper_bound(now+1,now+m+m+1,b[i].r)-now-1;
	i64 val=1ll*(pl-1)*b[i].l-sum[pl-1]+(sum[m+m]-sum[pr])-1ll*(m+m-pr)*b[i].r;
	if(val<mn) mn=val,pos=i;
    }
    ans+=mn,solve(l,mid-1,L,pos),solve(mid+1,r,pos,R);
}
int main()
{
    fread(ibuf,1,1<<23,stdin);
    m=read(),n=read(),k=read();
    for(int i=1;i<=k;++i) a[i]={read(),read()};
    std::sort(a+1,a+k+1,[](const node&a,const node&b){return a.l<b.l||(a.l==b.r&&a.r<b.r);});
    for(int i=1,mx=0;i<=k;++i) if(a[i].r>mx) mx=a[i].r,b[++tot]=a[i];
    for(int i=1;i<=m;std::sort(h[i].begin(),h[i].end()),++i) for(int j=1;j<=n+n;++j) h[i].push_back(read());
    solve(1,n,1,tot),printf("%lld",ans);
}
posted @ 2020-06-10 20:31  Shiina_Mashiro  阅读(368)  评论(0编辑  收藏  举报