• BZOJ 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle


    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

    思路:

      贪心的选取上下车,线段树维护是否可以上车,贪心的正确性显然,代码如下

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <iostream>
    #define ls p<<1
    #define rs p<<1|1
    #define im int mid = (l + r) >> 1
    using namespace std;
    const int N = 20000;
    const int inf = 0x3f3f3f3f;
    int k,n,c;
    int minn[N<<2],laz[N<<2];
    int tmp,ans;
    struct cow {
    	int s,t,m;
    }e[N<<2];
    bool cmp(const cow &a,const cow &b) {
    	return a.t==b.t?a.s>b.s:a.t<b.t;
    }
    void pushdown(int l,int r,int p,int s) {
    	minn[p]+=s;
    	laz[p]+=s;
    }
    void change(int l,int r,int p,int x,int y) {
    	if(x<=l&&r<=y) {
    		laz[p]+=tmp;
    		minn[p]+=tmp;
    		return ;
    	}
    	im;
    	if(laz[p]) {
    		pushdown(l,mid,ls,laz[p]);
    		pushdown(mid+1,r,rs,laz[p]);
    		laz[p]=0;
    	}
    	if(x<=mid)
    	change(l,mid,ls,x,y);
    	if(y>mid)
    	change(mid+1,r,rs,x,y);
    	minn[p]=max(minn[ls],minn[rs]);
    }
    void query(int l,int r,int p,int x,int y) {
    	if(x<=l&&r<=y) {
    		tmp=max(tmp,minn[p]);
    		return ;
    	}
    	im;
    	if(laz[p]) {
    		pushdown(l,mid,ls,laz[p]);
    		pushdown(mid+1,r,rs,laz[p]);
    		laz[p]=0;
    	}
    	if(x<=mid)
    	query(l,mid,ls,x,y);
    	if(y>mid)
    	query(mid+1,r,rs,x,y);
    }
    int main() {
    	scanf("%d%d%d",&k,&n,&c);
    	for(int i=1;i<=k;i++) {
    		scanf("%d%d%d",&e[i].s,&e[i].t,&e[i].m);
    	}
    	sort(e+1,e+k+1,cmp);
    	
    	for(int i=1;i<=k;i++) {
    		int tm;
    		int s=e[i].s,t=e[i].t,m=e[i].m;
    		tmp = 0;
    		query(1,n,1,s,t-1);
    		//printf("%d::::",tmp);
    		if(tmp>=c)continue;
    		if(tmp+m<=c)tm=m;
    		else tm=c-tmp;
    		tmp=tm;
    		change(1,n,1,s,t-1);
    		ans += tm;
    		//printf("%d %d %d
    ",s,t,tmp);
    	}
    	printf("%d
    ",ans);
    }
    

     欢迎来原博客看看 >原文链接<

  • 相关阅读:
    Hibernate 基于外键的双向一对一关联映射
    Hibernate 基于外键的单项一对一关联映射
    Hibernate inverse
    Hibernate cascade
    Hibernate 双向一对多的关联映射
    Hibernate 单项一对多的关联映射
    (转)关闭iptables和SELinux
    linux下大于2T的硬盘格式化方法
    lsusb命令
    CentOS最小化安装后启用无线连接网络
  • 原文地址:https://www.cnblogs.com/Tobichi/p/9079353.html
Copyright © 2020-2023  润新知