HihoCoder - 1053 常駐者の移行 (2 ポイント)

トピックリンク

西暦2411年、人類は地球以外の惑星に定住を始めた。植民地惑星 No.1326 には、N 個の集落が直線状に分布しています。説明の便宜上、i 番目の居住点の位置を居住者が住んでいる Xi と仮定します。冬の到来に伴い、人口密度の高い一部の集落では生態系の循環システムが過負荷になり始めています。厳しい冬を順調に乗り切るため、コロニーの住人たちは人口の少ない集落に移住することで人口の多い集落への負担を軽減することに同意した。

残念ながら、コロニー 1326 の環境は非常に厳しいです。冬が到来する前に、各集落の住民は距離がRを超えない集落に移住することができます。コロニー 1326 の住民は、移住完了後に最大人口の居住地が最小人口になるように移住を手配する方法を知りたいですか?

同じ場所に複数の集落が存在する場合があることに注意してください。

入力:
最初の行には、テスト データのグループの数を表す整数 T (1 <= T <= 10) が含まれています。

データの各セットの最初の行には、2 つの整数 N (1 <= N <= 100000) と R (0 <= R <= 10^9) が含まれています。

次の各 N 行には、2 つの整数 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

分析:
最大値の最小値を求める問題ですが、一般的にこのような問題は 2 つの点に分かれており、答えは 1e9 レベルになる可能性があるため、2 点の問題です。問題は 2 点あり、解決策のサイズをどのように判断するかです

この質問について: 1. iが現在の位置、jが転送可能な位置である
と仮定します。

2. 2 つの配列、つまり、native[k] と migration[k] を定義します。これらは、それぞれ居住点 k に移動できる居住者の数と、居住点 k から移住した居住者の数 (移動できなくなりました) を表します。居住者は居住地 k) にのみ入れることができます。

3. 次に、貪欲な方法を使用して、左から右に migration[j]=x を作成します (もちろん、native[j]=0 を保証するためですが、migration[j]=x、native[j] =0 の場合は必ずしもそうではありません)。 、次に j+1、migration=x を満たさない次の位置へ。

4. すべての最終決済のネイティブが 0 より大きい場合、現在の答え x が小さすぎることを意味します

#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cstring>
#include <stack>
#include <string>
using namespace std;

typedef long long ll;
const int N = 1e5+199;
const double Pi = acos(-1);
int T,n;
struct node{
    
    
    int xi;
    ll yi;
    bool operator < (const node &a) const{
    
    
        return xi<a.xi;
    }
}num[N];
ll migration[N],native[N],R;
bool Judge(ll x){
    
    
    int i=0,j=0;

    for(int i=0;i<n;i++) native[i]=num[i].yi,migration[i]=0;

    while(i<n && j<n ){
    
    
        if(abs(num[j].xi - num[i].xi) > R){
    
    
            if(j>i) return false;
            j++;
        }
        else{
    
    
            if(native[i]+migration[j]<=x){
    
    
                migration[j]+=native[i];
                native[i]=0;
                i++;
            }else{
    
    
                native[i]-=x-migration[j];
                migration[j]=x;
                j++;
            }
        }
    }
    for(int i=0;i<n;i++)
        if(native[i]>0) return false;
    return true;
}
ll Solve(ll lb,ll ub){
    
    
    while(lb<=ub){
    
    
        ll mid = (lb+ub)/2;

        if(Judge(mid))
            ub = mid - 1;
        else
            lb = mid + 1;
    }
    return lb - 1;
}
int main()
{
    
    

    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    scanf("%d",&T);
    while(T--){
    
    
        scanf("%d%lld",&n,&R);
        ll ub = 0;
        for(int i=0;i<n;i++)
            scanf("%d%lld",&num[i].xi,&num[i].yi),ub=max(ub,num[i].yi);

        sort(num,num+n);

        printf("%lld\n",Solve(0,ub));
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/c___c18/article/details/113993965