• [bzoj1359][Baltic2009]Candy


    给定N个数对$(T_i,S_i)$,表示时刻$S_i$时在位置$T_i$处出现一粒糖果。有一些机器人可供使用,每个机器人可花费一单位时间向相邻位置移动。要求用最少的机器人接到全部糖果。时刻0时机器人位置可自行安排。

    $1 leq N leq100000$, $0 leq S_i,T_i leq 10^9$。
    好题。首先可以想到转化成二维点对的问题。
    对于两点$(x,y)$和$(p,q)$,两点之间能连线的要求是$|x-p| geq |y-q|$。
    要求用最少的折线覆盖所有的点。
    我们只考虑时间小的向大的连边。不妨令$p<x$
    不考虑相等的情况下,对$x,p$,$y,q$的大小关系进行讨论。
    $left{egin{array}{l}x>p\y>qend{array} ight.$,这时还需满足$x-p geq y-q$;
    $left{egin{array}{l}x>p\y<qend{array} ight.$,这时还需满足$x-p geq q-y$;
    而如果$p>x$时
    $left{egin{array}{l}p>x\y>qend{array} ight.$或$left{egin{array}{l}p>x\q>yend{array} ight.$
    发现符合条件的两种情况都满足$x-y geq p-q$且$x+y geq p+q$。而两种不合法的均不满足两者其一。
    于是就转化成了二维偏序,,,点i的两个关键字如果都比点j大则可以连边。等于也是可以的。
    贪心的思路比较显然,保证$x+y$有序的前提下,找到$x-y$与小于等于当前$x-y$值,且差最小的那个。(更小的一定不更优)。如果找不到就新添加一个机器人。用set维护即可,复杂度$O(nlogn)$。
    #include<bits/stdc++.h>
    using namespace std;
    const int N=100010;
    typedef pair<int,int> P;
    inline int read(){
        int r=0,c=getchar();
        while(!isdigit(c))c=getchar();
        while(isdigit(c))
        r=r*10+c-'0',c=getchar();
        return r;
    }
    int ans,n;P a[N];
    set<int>S;
    set<int>::iterator it;
    int main(){
        ans=n=read();
        for(int i=1;i<=n;i++){
            int y=read(),x=read();
            a[i]=P(x+y,x-y);
        }
        sort(a+1,a+n+1);
        for(int i=1;i<=n;i++){
            int t=a[i].second;
            it=S.upper_bound(t);
            if(it!=S.begin())
            S.erase(--it),ans--;
            S.insert(t);
        }
        printf("%d
    ",ans);
    }
     
  • 相关阅读:
    【算法笔记】B1020 月饼
    JZOJ 3412. 【NOIP2013模拟】KC看星
    JZOJ 3517. 空间航行
    JZOJ 3515. 软件公司
    JZOJ 3514. 最小比例
    JZOJ 3490. 旅游(travel)
    luogu P3178 [HAOI2015]树上操作
    JZOJ 3427. 归途与征程
    JZOJ 3426. 封印一击
    JZOJ 3425. 能量获取
  • 原文地址:https://www.cnblogs.com/orzzz/p/8647561.html
Copyright © 2020-2023  润新知