#1053 : 居民迁移

http://hihocoder.com/problemset/problem/1053

Description

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

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

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

使用贪心,对每个位置,都找到能到达的范围内的最少人口点与之取平均,直至每个点的最大最小值都相隔最多为1为止,但是WA....题目给的example都通过了,不知道还有什么条件没有考虑到。。。目前WA

Input

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

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

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

Output

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


#include <stdlib.h>
#include <iostream>
#include <map>
#include <fstream>
#include <algorithm>
#include <vector>
#include <tr1/unordered_map>
using namespace std;
//#define _ONLINE 1
#ifndef _ONLINE
    ifstream fin("1053_ResidentsMigration.fin");
    #define input fin
#else
    #define input cin
#endif
#define MAX_N 100001
#define MAX_R 1000000001
struct Resident
{
    int X;
    int Y;
    bool operator<(const Resident& rh) {
        return Y<rh.Y;
    }
};
struct cmp
{
    bool operator()(const Resident& lh,const Resident& rh) {
        return lh.X<rh.X;
    }
};
//Resident g_node[MAX_N];
typedef vector<Resident> ResidentArr;
int T,N,R;
enum Type
{
    _MIN=0,
    _MAX
};
ostream& operator<<(ostream& os,ResidentArr& arr)
{
    for(auto ele:arr)
        os<<ele.Y<<" ";
    os<<endl;
    return os;
}
int find(ResidentArr& nodes,int s,int e,int type)
{
    if(e<s)
        return -1;
    if(e==s)
        return s;
    int m=s+(e-s)/2;
    int left=find(nodes,s,m,type);
    int right=find(nodes,m+1,e,type);
    if(type==_MIN)
        return nodes[left]<nodes[right]?left:right;
    else
        return nodes[left]<nodes[right]?right:left;
}
void findRange(ResidentArr& nodes,int i,int& s,int& e,int m,int n)
{
    e=i+1;
    while(e<=n&&(nodes[e].X-nodes[i].X)<=R)
        e++;
    e--;
    s=i-1;
    while(s>=m&&(nodes[i].X-nodes[s].X)<=R)
        s--;
    s++;
}
int find(ResidentArr& nodes,int i,int type,int m,int n)
{
    int s,e;
    findRange(nodes,i,s,e,m,n);
    //cout<<"find in #"<<s<<" "<<e<<endl;
    return find(nodes,s,e,type);
}
int average(ResidentArr& srcArr,int maxIndex,int minIndex)
{
    if(maxIndex!=minIndex&&srcArr[maxIndex].Y>srcArr[minIndex].Y+1) 
    {
        size_t s=srcArr[maxIndex].Y+srcArr[minIndex].Y;
        int a=floor(s/2);
        int b=s-a;
        srcArr[maxIndex].Y=b;
        srcArr[minIndex].Y=a;
        return 1;
    }
    else
        return 0;
}
int solve(ResidentArr& srcArr,int m,int n) 
{
    while(true) 
    {
        int move=0;
        for(int i=m;i<=n;i++) 
        {
            int minIndex=find(srcArr,i,_MIN,m,n);
            move+=average(srcArr,i,minIndex);
            cout<<i<<"#"<<srcArr[minIndex].X-srcArr[i].X<<"#\t"<<srcArr;
        }
        if(move==0)
            break;
    }
    int result=find(srcArr,m,n,_MAX);
    cout<<srcArr[result].Y<<endl;
    return 0;
}
void test(ResidentArr& nodes) {
    static size_t caseCnt=0;
    cout<<"case#"<<caseCnt++<<endl;
    for(int i=0;i<N;i++)
    {
        int index=find(nodes,i,_MIN,0,N-1);
        //cout<<"[0, "<<i<<" ], min: "<<index<<"#"<<g_node[index].Y<<endl;
        cout<<i<<"#min: "<<index<<"#"<<nodes[index].Y<<endl;
    }
}
int main(){
    input>>T;
    while(T--) {
        input>>N>>R;
        ResidentArr nodes;
        tr1::unordered_map<int,int> nmap;
        for(int i=0;i<N;i++) {
            int X,Y;
            input>>X>>Y;
            if(!nmap[X]) {
                nmap[X]=i;
                nodes.push_back({X,Y});
            }
            else
                nodes[nmap[X]].Y+=Y;
        }
        sort(nodes.begin(),nodes.end(),cmp());
        solve(nodes,0,N-1);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值