分治算法

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);   
}
posted @ 2019-10-20 19:37  ALEZ  阅读(651)  评论(0编辑  收藏  举报