[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$。



想法:开始觉得是个裸贪心,但是没法维护。其实是这样的:

我们将所有的奶牛群排序:右端点为第一关键字,递增;左端点为第二关键字,递减。

我们给序列上的每个数是当前公交车剩的奶牛个数。然后就是用线段树维护区间最小值,答案就加上当前奶牛群和对应区间的最小值的较小者,然后区间加。

即可。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 20010
#define K 50010
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
int minn[N<<2],tag[N<<2]; int c;
struct Node {int l,r,w;}a[K]; inline bool cmp(const Node &x,const Node &y) {return x.r==y.r?x.l>y.l:x.r<y.r;}
inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
int rd() {int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
inline void pushup(int pos) {minn[pos]=min(minn[lson],minn[rson]);}
inline void pushdown(int pos)
{
    if(!tag[pos]) return;
    tag[lson]+=tag[pos]; minn[lson]+=tag[pos];
    tag[rson]+=tag[pos]; minn[rson]+=tag[pos];
    tag[pos]=0;
}
void build(int l,int r,int pos)
{
    if(l==r) {minn[pos]=c; return;}
    int mid=(l+r)>>1;
    build(l,mid,lson); build(mid+1,r,rson);
    pushup(pos);
}
void update(int x,int y,int val,int l,int r,int pos)
{
    if(x<=l&&r<=y) {minn[pos]+=val; tag[pos]+=val; return;}
    int mid=(l+r)>>1; pushdown(pos);
    if(x<=mid) update(x,y,val,l,mid,lson);
    if(mid<y) update(x,y,val,mid+1,r,rson);
    pushup(pos);
}
int query(int x,int y,int l,int r,int pos)
{
    if(x<=l&&r<=y) return minn[pos];
    int mid=(l+r)>>1,ans=0x7f7f7f7f; pushdown(pos);
    if(x<=mid) ans=min(ans,query(x,y,l,mid,lson));
    if(mid<y) ans=min(ans,query(x,y,mid+1,r,rson));
    return ans;
}
int main()
{
    int n=rd(),l=rd(); c=rd(); for(int i=1;i<=n;i++)
    {
        a[i].l=rd(),a[i].r=rd(),a[i].w=rd(); a[i].r--;
    }
    int ans=0;
    sort(a+1,a+n+1,cmp); build(1,l,1);
    for(int i=1;i<=n;i++)
    {
        int temp=min(a[i].w,query(a[i].l,a[i].r,1,l,1));
        if(temp) ans+=temp,update(a[i].l,a[i].r,-temp,1,l,1);
    }
    printf("%d\n",ans);
    return 0;
}

小结:线段树是真的强啊... ...

原文地址:https://www.cnblogs.com/ShuraK/p/9669663.html

时间: 2024-08-07 12:57:13

[bzoj1577][Usaco2009 Feb]庙会捷运Fair Shuttle_贪心_线段树的相关文章

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

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

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..

[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

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

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】 1579: [Usaco2009 Feb]Revamping Trails 道路升级 (最短路)

1579: [Usaco2009 Feb]Revamping Trails 道路升级 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 <= 1,000,000)时间单位用道路i从P1_i走到P2_i或者从P2_i 走

bzoj3398[Usaco2009 Feb]Bullcow 牡牛和牝牛*

bzoj3398[Usaco2009 Feb]Bullcow 牡牛和牝牛 题意: n头牛,其中有牡牛和牝牛两种,要求任意两只牡牛中要有k只牝牛,问几种方案.n≤100000 题解: dp.f[i]表示第i头牛为牡牛的方案数,f[i]=sigma(j,1,i-k-1)f[j],这个可以用前缀和维护,最后答案为sigma(i,1,n)f[i]. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm&g

台北捷运杀人案二审 嫌犯想道歉遭拒绝

中新网4月27日电 据台湾东森新闻云报道,犯下捷运杀人案的郑捷,台北地院一审以一罪一罚的方式判他4个死刑,台湾高等法院27日首度开庭,郑捷出庭时面无表情,通过律师表示认罪,当庭声明撤回上诉,但又说一审判他死刑违反两公约及“宪法”比例原则,坚称自己不能被判死. 带着手铐脚镣,郑捷缓缓走上阶梯,上午高院首度开庭审理,面对记者提问他不发一语,表情还是一样冷酷:案件发生至今快1年,郑捷头发长了.脸上有胡渣,但不变的是他的眼神,每次面对镜头都像是在瞪人. 年仅21岁的他犯下捷运随机杀人案,酿成4死22伤惨

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;