zoukankan      html  css  js  c++  java
  • 【BZOJ】1577: [Usaco2009 Feb]庙会捷运Fair Shuttle

    【题意】公车从1开到n,有k群牛想从一个点到达另一个点,公车最多乘坐c个人,牛群可以拆散,问最多载多少牛到达目的地。

    【算法】贪心+堆

    【题解】线段和点的贪心,一般有按左端点排序和按右端点排序两种方法。

    按左端点排序,到达了终点就下车,人数满了就贪心地删掉当前终点最远的牛。

    正确性在于,在对左一致的情况下,优先删除对右影响最大的牛。

    本来以为很难实现,但是想清楚之后写起来十分顺畅,还是要有信心><

    对于到达终点下车,按终点维护小根堆。

    对于满人数贪心删终点最大的,维护大根堆。

    用标号vis和剩余牛数num连接两个堆的删除。

    复杂度O(k log k)。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxn=200010;
    struct cycmax{
         int id,ed;
         bool operator < (const cycmax &a)const{
             return ed<a.ed;
         }
    };
    priority_queue<cycmax>cmax;
    struct cycmin{
        int id,ed;
        bool operator < (const cycmin &a)const{
            return ed>a.ed;
        }
    };
    priority_queue<cycmin>cmin;
    struct cyc{
        int l,r,num;
    }a[maxn];
    bool cmp(cyc a,cyc b){return a.l<b.l;}
    int k,n,c,ans=0,number=0;
    bool vis[maxn];
    int main(){
        scanf("%d%d%d",&n,&k,&c);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].num);
        }
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;i++){
            cmax.push((cycmax){i,a[i].r});
            cmin.push((cycmin){i,a[i].r});
            number+=a[i].num;
            if(a[i].l!=a[i+1].l){
                while(!cmin.empty()&&cmin.top().ed<=a[i].l){
                    cycmin x=cmin.top();
                    if(!vis[x.id]){
                        ans+=a[x.id].num;
                        number-=a[x.id].num;
                        vis[x.id]=1;
                    }
                    cmin.pop();
                }
                while(number>c){
                    cycmax x=cmax.top();
                    if(!vis[x.id]){
                        if(number-a[x.id].num>=c){
                            number-=a[x.id].num;
                            vis[x.id]=1;
                            cmax.pop();
                        }
                        else{
                            a[x.id].num-=number-c;//zhu yi shun xu le!!!
                            number=c;
                        }
                    }else cmax.pop();
                }
            }
        }
        while(!cmax.empty()){
            cycmax x=cmax.top();cmax.pop();
            if(!vis[x.id])ans+=a[x.id].num;
        }
        printf("%d",ans);
        return 0;
    }
    View Code

    另一种做法,按右端点排序,能塞就塞,不能塞就不要,用线段树维护。(感性的理解一下,替换之前的效果一样却反而会占用到后面的,既然前面能解决的事为什么要交给后面的)

  • 相关阅读:
    Voice over IP
    [转】:TCP/IP详解学习笔记(5)
    windows phone 7 version: ObservableCollectionEx (1)
    MA0003 移动智能网原理
    TCP 网络书籍
    windows Phone 7如何实现background的情况下不丢失数据
    最近想要学习和了解的东东
    Windows phone 7 开发注意事项
    android Tab标签下得按钮
    新浪微博教程(一)
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7689303.html
Copyright © 2011-2022 走看看