bzoj 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle——小根堆+大根堆+贪心

Description

公交车一共经过N(1<=N<=20000)个站点,从站点1一直驶到站点N。K(1<=K<=50000)群奶牛希望搭乘这辆公交车。第i群牛一共有Mi(1<=Mi<=N)只.

他们希望从Si到Ei去。
公交车只能座C(1<=C<=100)只奶牛。而且不走重复路线,请计算这辆车最多能满足多少奶牛听要求。
注意:对于每一群奶牛,可以部分满足,也可以全部满足,也可以全部不满足。

Input

第1行: 三个整数: K,N,C。 由空格隔开。

第2..K+1行:第i+1行,告诉你第i组奶牛的信息: S_i, E_i and M_i。由空格隔开。

Output

一行:可以在庙会乘坐捷运的牛的最大头数

Sample Input

8 15 3

1 5 2

13 14 1

5 8 3

8 14 2

14 15 1

9 12 1

12 15 2

4 6 1

Sample Output

10

HINT

捷运可以把2头奶牛从展台1送到展台5,3头奶牛从展台5到展台8,

2头奶牛从展台8 到展台14,1头奶牛从展台9送到展台12,

一头奶牛从展台13送到展台14, 一头奶牛从 14送到15。

——————————————————————————————

这道题我们维护两个堆 按终点距离为键值 维护一个大根堆 一个小根堆

我们每次到一个点 就把所有到这个点(作为终点)的奶牛扔出堆(大根堆小根堆的信息要互通)

表示他们已经下车了 到一个点之后把所有在这个点上车的牛全部扔进堆 表示他们要上车辣QAQ

如果这个时候车上的人太多了(会出事的2333) 我们就贪心地把终点最远的扔出堆

这样就可以得到最优解了2333

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
const int M=3e4+7;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
int f[2*M],cnt,cost,k,n,c,ans;
struct pos{
    int id,h,ed;
    bool operator <(const pos &x)const{return x.ed<ed;}
};
std::vector<pos>e[M];
std::priority_queue<pos>q1;
struct Q{
    int id,h,ed;
    bool operator <(const Q &x)const{return x.ed>ed;}
};
std::priority_queue<Q>q2;
int main(){
    int v,x,y;
    k=read(); n=read(); c=read();
    for(int i=1;i<=k;i++) x=read(),y=read(),v=read(),e[x].push_back((pos){++cnt,v,y});
    for(int i=1;i<=n;i++){
        while(!q1.empty()){
            pos x=q1.top();
            if(x.ed>i) break;
            q1.pop();
            if(f[x.id]) continue;
            f[x.id]=1; cost-=x.h; ans+=x.h;
        }
        int mx=e[i].size();
        for(int j=0;j<mx;j++){
            q1.push((pos){e[i][j].id,e[i][j].h,e[i][j].ed});
            q2.push((Q){e[i][j].id,e[i][j].h,e[i][j].ed});
            cost+=e[i][j].h;
        }
        while(cost>c){
            Q x=q2.top(); q2.pop();
            if(f[x.id]) continue;
            f[x.id]=1;
            if(cost-c>=x.h){cost-=x.h; continue;}
            int now=cost-c;
            cnt++;
            q1.push((pos){cnt,x.h-now,x.ed});
            q2.push((Q){cnt,x.h-now,x.ed});
            cost=c;
        }
    }
    printf("%d\n",ans);
    return 0;
}

时间: 2024-11-08 00:29:55

bzoj 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle——小根堆+大根堆+贪心的相关文章

bzoj 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle【贪心+线段树】

按结束时间排序,然后开个线段树,按照排序后的牛群贪心的选 贪心的依据是选哪头牛都是选,不如给后面的多省一点空间 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=50005; int m,n,c,ans; struct xds { int l,r,mn,lz; }t[N<<1]; struct qwe { int s,t,m; }a

[Usaco2009 Feb]庙会捷运Fair Shuttle

Description 公交车一共经过N(1<=N<=20000)个站点,从站点1一直驶到站点N.K(1<=K<=50000)群奶牛希望搭乘这辆公交车.第i群牛一共有Mi(1<=Mi<=N)只. 他们希望从Si到Ei去. 公交车只能座C(1<=C<=100)只奶牛.而且不走重复路线,请计算这辆车最多能满足多少奶牛听要求. 注意:对于每一群奶牛,可以部分满足,也可以全部满足,也可以全部不满足. Input 第1行: 三个整数: K,N,C. 由空格隔开. 第2

BZOJ1577: [Usaco2009 Feb]庙会捷运Fair Shuttle

n<=20000个车站,车能同时载C<=100个人,求能满足K<=50000群人的多少个.每群人给起点终点和人数,一群人不一定要都满足. 一开始想DP,想不出,很菜. 贪心即可.如果有右端点相同的几群人,那肯定优先满足左端点大的:如果有两群人发生冲突,而我们从左到右考虑区间的话,那肯定让左边的人先满足,因为他对后面的人影响小.所以先排个序然后模拟即可.模拟用线段树. 1 #include<stdio.h> 2 #include<string.h> 3 #inclu

[bzoj1577][Usaco2009 Feb]庙会捷运Fair Shuttle_贪心_线段树

庙会捷运 Fair Shuttle bzoj-1577 Usaco-2009 Feb 题目大意:有一辆公交车从1走到n.有m群奶牛从$S_i$到$E_i$,第i群奶牛有$W_i$只.车有一个容量c.问不走回头路的情况下最多使多少奶牛到达目的地.其中,每一群奶牛不一定都拉走. 注释:$1\le n\le 2\cdot 10^4$,$1\le m\le 5\cdot 10^4$,$1\le c\le 100$. 想法:开始觉得是个裸贪心,但是没法维护.其实是这样的: 我们将所有的奶牛群排序:右端点为

BZOJ 3398: [Usaco2009 Feb]Bullcow 牡牛和牝牛( dp )

水题...忘了取模就没1A了.... --------------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; const int MOD = 5000011; const int maxn = 100009; int dp[maxn], n, k; int main() { cin >> n >> k;

Bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 dijkstra,堆,分层图

1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1573  Solved: 428[Submit][Status][Discuss] Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N;

BZOJ 1579: [Usaco2009 Feb]Revamping Trails 道路升级( 最短路 )

最短路...多加一维表示更新了多少条路 ---------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<iostream> #define rep( i , n ) for( int i

bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 优先队列+dij

1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1768  Solved: 481[Submit][Status][Discuss] Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N;

bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 -- 分层图最短路

1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MB Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N; 1 <= P2_i<= N). John需要T_i (1 <= T_i <