• 分治算法


    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);   
    }
    
  • 相关阅读:
    如何查看ubuntu版本
    基于Python与命令行人脸识别项目(系列一)
    问题 B: Curriculum Vitae
    问题 M: 克隆玩具
    1906: 鹊桥相会
    3265: 聪明的矿工
    2363: 完美旗手队列
    2545: 内部收益率
    2544: 台球碰撞
    3272: 公民身份号码
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11708740.html
Copyright © 2020-2023  润新知