[USACO NOV]金发姑娘和N头牛

1435. [USACO NOV]金发姑娘和N头牛

★☆   输入文件: milktemp.in   输出文件: milktemp.out    简单对比
时间限制:1 s   内存限制:256 MB

【题目描述】


你可能已经听说了金发姑娘和3只熊的经典故事。

鲜为人知的是,金发姑娘最终经营了一个农场。在她的农场,她有一个谷仓含N头奶牛(1<=N <= 20000)。不幸的是,她的奶牛对温度相当敏感。

第i头奶牛必须在指定的温度范围内A(i)..B(i)才感觉舒适;(0<=A(i)<=B(i)<= 1,000,000,000)。如果金发姑娘在谷仓放置一个温控器;如果温度T<A(i),牛会太冷,并将产生x单位牛奶。如果她把恒温器调到(A(i)<=T<=B(i))这个范围内,那么牛会感到舒适,并将产生Y单位牛奶。如果她把恒温器调到温度T>B(i),牛会感觉很热,并将产生的Z单位牛奶。正如预期的那样,Y的值总是大于X和Z。

给定的X,Y,和Z,以及每个牛的温度的最佳范围,如果金发姑娘设置谷仓的温控器最佳,请计算金发姑娘得到牛奶的最大数量,已知X,Y和Z都是整数,范围0..1000。温控器可以设置为任意整数的值。


【输入格式】


第1行:四个用空格隔开的整数:N X Y Z。

第2行..1 + N:行1+i包含两个用空格隔开的整数:A(i)和B(i)。


【输出格式】


1行:金发姑娘最多可以获得的牛奶,当她在谷仓的最佳温度设定。

【样例输入】

4 7 9 6 5 8 3 4 13 20 7 10

【样例输出】

31

【提示】


在农场里有4头奶牛,温度范围5..8,3..4,13..20,10..7。一个寒冷的奶牛生产7单位的牛奶,一个舒适的奶牛生产9个单位的牛奶,一个热牛生产6单位牛奶。


【数据规模】


50%的测试数据:n<=5

其余50%的测试数据:10000<n<=20000.


【来源】

USACO 2013 November Contest, Bronze


这道题利用差分的思想,

无非只有三个区间: 

   1: [1, A(i)-1] 在c[0]的位置加上x;

   2:  [ A(i), B(i)] 在c[A(i)] 的位置上加上y-x;

   3:  [B(i)+1, n ] 在B(i)+1的位置上加上z-y;

这样,查询某个温度的前缀和,就是奶牛在这个温度产生的牛奶量;


但是, A(i)与B(i)的范围太大, N 又那么小, 所以我们不难想到用离散化;

观察以上区间,其实只有三个点有用,0, A(i), B(i)+1, ;这三个点完全可以代替这三个区间;

所以我们只需保留A(i),B(i)的相对位置就行, 就是不用知道具体多大, 比他大的还在他后面,比他小的还在他前面;

这就是所谓的离散化;(本蒟蒻的见解)

因为每个A(i),B(i)+1, 要加的值是一样的,所以A(i), B(i)的顺序打乱后并不影响结果,这样就可以把他们排序,以便离散;


代码来也:


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;

const int maxn=20000+10;
const int INF=0x3f3f3f3f;

map<int, int> m;
int L[maxn], R[maxn], c[maxn];
int n, cnt, x, y, z;
int ans, sum;

int main() {
	freopen("milktemp.in", "r", stdin);
	freopen("milktemp.out", "w", stdout);
	scanf("%d%d%d%d", &n, &x, &y, &z);
	for(int i=1; i<=n; i++) scanf("%d%d", &L[i], &R[i]), R[i]++;
	sort(L+1, L+n+1); sort(R+1, R+n+1);
	int h=1, t=1;
	while(1) {
		if(h<=n && L[h]<R[t]) {
			if(!m.count(L[h])) m[L[h]]=++cnt;
			c[m[L[h]]]+=y-x;
			h++;
		}  
		else if(t<=n) {
			if(!m.count(R[t])) m[R[t]]=++cnt;
			c[m[R[t]]]+=z-y;
			t++;
		}
		if(h>n && t>n) break;
	}
	ans=sum=n*x;<span style="white-space:pre">			//这句话相当于在c[0]加上n个x; 简化了而已;</span>
	for(int i=1; i<=cnt; i++) {
		sum+=c[i];<span style="white-space:pre">		//sum不断累加,其实就是前缀和;</span>
		ans=max(ans, sum);
	}
	printf("%d", ans);
	return 0;
}





  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值