B「ROI 2019 Day2」课桌
时间限制 : 16000 MS 空间限制 : - KB
评测说明 : 1s,512m
问题描述
有 m 个班,每个班有 2*N 名学生。各班将轮流来到一个会议室上课,每次只有一个班在会议室。
你需要给会议室购买 N张双人课桌。
供你选择的课桌分为 K类,分别编为 1...K 号,I 号课桌适合身高在Li 到 Ri 之间的学生。
学生使用太高或太矮的课桌会感到不适,这可用「不适指数」表示,具体来说:
对于身高在这一区间内的学生,其不适指数为 0;
对于身高小于Li 的学生,设身高为h ,则其不适指数为 h-Li;
对于身高大于Ri 的学生,设身高为 h,则其不适指数为 Ri-h。
请求出:在课桌最合适的情况下,这 2mn 名学生的不适指数的最小值。
解:
将n张桌子看做商品
那么对于第i号商品 适用于2i 到2i-1 号学生
假设我们对于k个商品进行排序去重
注意到 对于i号商品 如果匹配u号桌子
那么[1,u-1 ]一定不会去匹配i及其以后的商品
这符合分治的条件
然后就可以进行分治
//
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxnn 200005
typedef pair<ll,ll > P;
ll tot=0;
P a[maxnn],b[maxnn];
ll *c[maxnn];
ll n,m,k;
#define GC getchar()
inline ll R()
{
char t;
ll x=0;
t=GC;
while(!isdigit(t)) t=GC;
while(isdigit(t))
{
x=x*10+t-'0';
t=GC;
}
return x;
}
ll get(int x,int y,int l,int r)
{
if(x>y)
{
return 0;
}
static ll v[2*maxnn],lsum[2*maxnn],rsum[2*maxnn];
ll ttt=0;
ll sum=0;
ll mid=(x+y)>>1;
for(int i=1;i<=m;i++)
{
v[++ttt]=c[i][mid*2];
v[++ttt]=c[i][mid*2-1];
}
sort(v+1,v+1+ttt);
for(int i=1;i<=ttt;i++)
{
lsum[i]=lsum[i-1]+v[i];
}
for(int i=ttt;i>=1;i--)
{
rsum[i]=rsum[i+1]+v[i];
}
ll tmp=0;
ll pos=0;
ll now=11111110000000000;
for(int i=l;i<=r;i++)
{
pos=0;
ll k1=upper_bound(v+1,v+1+ttt,b[i].second)-v;
ll k2=upper_bound(v+1,v+1+ttt,b[i].first)-v;
if(k1<ttt+1)
{
pos+=(rsum[k1])-(ll)(ttt-k1+1)*(b[i].second);
}
if((k2-1)>=0)
{
k2--;
pos+=(ll)(k2)*(b[i].first)-(lsum[k2]);
}
if(pos<now)
{
now=pos;
tmp=i;
}
}
sum=now;
sum+=get(x,mid-1,l,tmp);
sum+=get(mid+1,y,tmp,r);
return sum;
}
int main()
{
ll x,y;
cin>>m>>n>>k;
for(int i=1;i<=k;i++)
{
x=R();
y=R();
a[i].first=x; a[i].second=y; //L R
}
sort(a+1,a+1+k);
for (int i = 1; i <= k; i++)
if (a[i].second>a[i - 1].second)
b[++tot] = a[i]; //B [L,R]
sort(b+1,b+1+tot);
for(int i=1;i<=m;i++)
{
c[i]=new ll[2 * n + 1];
for(int j=1;j<=2*n;j++)
{
x=R();
c[i][j]=x;
}
sort(c[i]+1,c[i]+1+2*n);
}
cout<<get(1,n,1,tot);
}