zoukankan      html  css  js  c++  java
  • HihoCoder 1053 : 居民迁移 二分+贪心+双指针(好题)

     居民迁移

    时间限制:3000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    公元2411年,人类开始在地球以外的行星建立居住点。在第1326号殖民星上,N个居住点分布在一条直线上。为了方便描述,我们设第i个居住点的位置是Xi,其中居住着Yi位居民。随着冬季的到来,一些人口较多的居住点的生态循环系统已经开始超负荷运转。为了顺利度过严冬,殖民星上的居民一致同意通过转移到人口较少的居住点来减轻人口众多的居住点的负荷。

    遗憾的是,1326殖民星的环境非常恶劣。在冬季到来前,每个居民点的居民最远能迁移到距离不超过R的居民点。1326殖民星的居民希望知道,如何安排迁移才能使完成迁移后人口最多的居民点人口最少?

    注意有可能存在多个居民点位置相同。

    输入

    第一行包含一个整数T(1 <= T <= 10),代表测试数据的组数。

    每组数据的第一行包含2个整数N(1 <= N <= 100000)和R(0 <= R <= 10^9)。

    以下N行每行包含两个整数,Xi和Yi(0 <= Xi, Yi, <= 10^9)。

    输出

    对于每组数据输出迁移后人口最多的居民点人口最少可能的数目。

    样例输入
    3  
    5 1  
    10 80  
    20 20  
    30 100  
    40 30  
    50 10  
    5 10  
    10 80  
    20 20  
    30 100   
    40 30  
    50 10  
    5 20  
    10 80  
    50 10  
    20 20  
    30 100  
    40 30 
    样例输出
    100  
    50  
    48

    仨个铺垫:

                       如果没有距离不超过R的限制,直接总和除个数即可。

                       如果知道上界,像“纸牌移动”一样贪心就行。

                       求最大值最小化,二分既可。

    正题:

                       初步思路:难度是预处理每个点的范围,然后最大流来判断是否满流?

                       再步思路:由于范围肯定是连续处理得到最优,所以用双指针。

    自己YY的双指针代码,丑是情有可原的,不过1A了,丑不丑无所谓lia。

    不懂双指针的可以去看hihocoder1607辣。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int maxn=100010;
    int a[maxn],b[maxn];
    int L,R,r,n;
    struct in
    {
        int x;
        int y;
    }s[maxn];
    
    bool cmp(in a,in b){
        return a.x<b.x;
    }
    
    bool check(int u)
    {
         int p=1,m=1;//p是待装,m是容器指针
         for(int i=1;i<=n;i++){
              a[i]=s[i].y;b[i]=0;//a是待装,b是容器
         }
         while(p<=n&&m<=n){
              while(p<=n&&s[m].x-s[p].x>r) {
                   if(a[p]>0) return false;
                   p++;
              }
              while(m<=n&&p<=n){
                   if(s[p].x-s[m].x>r||b[m]==u) { m++;break; }
                   int tmp=min(a[p],u-b[m]);
                   a[p]-=tmp; b[m]+=tmp;
                   if(a[p]==0) p++;
              }
         }
         for(int i=1;i<=n;i++) if(a[i]>0) return false;
         return true;
    }
    int main()
    {
          int i,j,T;    
          scanf("%d",&T);
          while(T--){
                L=R=1;
                scanf("%d%d",&n,&r);
                for(i=1;i<=n;i++){
                    scanf("%d%d",&s[i].x,&s[i].y);
                    R=max(R,s[i].y);
                }
                sort(s+1,s+n+1,cmp);
                while(L<R){
                    int mid=(L+R)/2;
                    if(check(mid)) R=mid;
                    else L=mid+1;
                }
                printf("%d
    ",L);
          }
          return 0;
    }
     
  • 相关阅读:
    如何解决列表框控件宽度不够的问题
    SQL Server 2005的服务器角色(public)的问题
    使用多结果集读取数据减少服务器往返,提高性能
    SQL SERVER的单用户模式以及专用管理员连接
    SQL Server错误严重性级别和异常处理
    使用TransactionScope做分布式事务协调
    通过编程为Outlook 2007添加邮件规则
    微软中国的相关研发团队 交流平台
    有关连接字符串的一些细节
    Web Application和Web Site两个模板的比较
  • 原文地址:https://www.cnblogs.com/hua-dong/p/7794654.html
Copyright © 2011-2022 走看看