luogu_P2869 【[USACO07DEC]美食的食草动物Gourmet Grazers】

写此题时并不会multiset,就写了个树状数组

先把100,000,000的数据离散化了,最多就对映到1-200,000(理由见数据范围

权值树状数组,即1-200,000的范围

排序后贪心思路是一样的,查询第1个大于等于是什么数时就二分

初始区间为

左端点:当前奶牛花钱最小值

右端点:N+M

树状数组查询区间是否有数(即区间和),有数就缩小右端点(区间和不为零),否则增大左端点

无解情况就是有一头奶牛初始区间和为0

不过multiset,确实方便许一些,而且快得多

二维偏序思想:先保证一维有序

#include<iostream>
#include<cstdio>

#define ri register int
#define u long long

namespace opt {

    inline u in() {
        u x(0),f(1);
        char s(getchar());
        while(s<'0'||s>'9') {
            if(s=='-') f=-1;
            s=getchar();
        }
        while(s>='0'&&s<='9') {
            x=(x<<1)+(x<<3)+s-'0';
            s=getchar();
        }
        return x*f;
    }

}

using opt::in;

#define NN 200005

#include<algorithm>

namespace mainstay {

    u N,M,ans(0),now(1),t[NN],cnt,len,pre[NN],w[NN<<1];

    struct node {
        u x,y;
    } a[NN],b[NN];

    void add(const u &x,const u &y) {
        for(ri i(x); i<=N+M; i+=i&-i) t[i]+=y;
    }

    u ask(const u &x) {
        u _re(0);
        for(ri i(x); i>=1; i-=i&-i) _re+=t[i];
        return _re;
    }

    inline bool cmp(const node &x,const node &y) {
        return x.y>y.y;
    }

    void li_sanhua() {
        cnt=0;
        for(ri i(1); i<=N; ++i) w[++cnt]=a[i].x;
        for(ri i(1); i<=M; ++i) w[++cnt]=b[i].x;
        std::sort(w+1,w+cnt+1),len=std::unique(w+1,w+cnt+1)-w-1;
        for(ri i(1); i<=N; ++i) pre[std::lower_bound(w+1,w+len+1,a[i].x)-w]=a[i].x;
        for(ri i(1); i<=M; ++i) pre[std::lower_bound(w+1,w+len+1,b[i].x)-w]=b[i].x;
        for(ri i(1); i<=N; ++i) a[i].x=std::lower_bound(w+1,w+len+1,a[i].x)-w;
        for(ri i(1); i<=M; ++i) b[i].x=std::lower_bound(w+1,w+len+1,b[i].x)-w;
        cnt=0;
        for(ri i(1); i<=N; ++i) w[++cnt]=a[i].y;
        for(ri i(1); i<=M; ++i) w[++cnt]=b[i].y;
        std::sort(w+1,w+cnt+1),len=std::unique(w+1,w+cnt+1)-w-1;
        for(ri i(1); i<=N; ++i) a[i].y=std::lower_bound(w+1,w+len+1,a[i].y)-w;
        for(ri i(1); i<=M; ++i) b[i].y=std::lower_bound(w+1,w+len+1,b[i].y)-w;
    }

    inline void solve() {
        N=in(),M=in();
        for(ri i(1); i<=N; ++i) a[i].x=in(),a[i].y=in();
        for(ri i(1); i<=M; ++i) b[i].x=in(),b[i].y=in();
        li_sanhua(),std::sort(a+1,a+N+1,cmp),std::sort(b+1,b+M+1,cmp);
        for(ri i(1); i<=N; ++i) {
            while(b[now].y>=a[i].y) add(b[now].x,1),++now;
            u _re,_l(a[i].x),_r(N+M);
            if(!(ask(_r)-ask(_l-1))) {
                printf("-1");
                return;
            }
            while(_l<=_r) {
                u mid(_l+_r>>1);
                if((ask(mid)-ask(_l-1))>0) _r=mid-1,_re=mid;
                else _l=mid+1;
            }
            ans+=pre[_re],add(_re,-1);
        }
        std::cout<<ans;
    }

}

int main() {

    //freopen("food.in","r",stdin);
    //freopen("food.out","w",stdout);
    std::ios::sync_with_stdio(false);
    mainstay::solve();

}

转自本人自己的luogu博客。

原文地址:https://www.cnblogs.com/ling-zhi/p/11813455.html