贪心+优先队列

游戏通关

(game.pas/c/c++)

【问题描述】

   XY 经常在机房里偷偷玩游戏,于是他也经常被CJH 教练批评。但屡次的批评一点作用也没有,你看他又开始玩起了游戏。

    这次XY 可碰上难题了,因为据可靠的线报CJH 教练在不久后就回来机房,但XY 需要完成N 个任务才能将这个游戏通关。

    每个任务完成时限T,就是这个任务必须在时间T 之前完成(你可以认为游戏刚开始的时间为1),还有完成这个任务XY 可以获得一定的奖励W。由于XY 娴熟的技术以及任务的简单,他可以在一个单位时间将任务完成。

   XY想要在CJH 教练到来之前将任务全部完成,同时他也想获得最多的奖励。这个他本来可以编程自己完成的,但是为了能马上将游戏通关,他需要全神贯注进去。于是他没有空编程计算,于是他希望你能帮助他将问题的答案计算出来。

【输入格式】

    第一行有一个整数N ,表示需要完成的任务数目;

    接下来N  行,每行两个整数T,W  (中间用一个空格隔开),分别表示完成这个任务的最后期限和完成这个任务后获得的奖励。

【输出格式】

    输出数据有且仅有一行,只包含一个整数S,表示最多获得的奖励。

【输入样例1】game.in

    2

    15

    14

【输出样例2】game.out

    5

【输入样例2】

    5

    23

    12

    45

    13

    34

【输出样例2】

   15

【样例解释】

    对于样例2 XY 可以选择完成任务1,3,4 和5,这样他可以获得奖励15。

【数据规模】

    对于10%的数据,N≤100,Ti≤100,Wi≤2000;

    对于30%的数据,N≤1000,Ti≤5000,Wi≤2000;

    对于50%的数据,N≤10000,Ti≤20000,Wi≤2000;

对于100%的数据,N≤200000,Ti≤200000,Wi≤2000 。



这估计是最后一次模拟赛了。。。。但是智商问题让我错失一次AK!!!!

显然本题可以贪心+优先队列。。

将所有物品按时间从大到小排好,然后按时间从后往前扔进去,显然局部最优解就是全局最优解


但是苟蒻做的时候没想到。。。

将物品价值从大到小排,显然大的物品能放总是最好的

放的时候尽量往后塞总是最好的

于是想到线段树

于是写错了?!!

虽然查询时往右边走总是好但是右边存在的可能是超出当前范围的点啊!

所以要特判。。。


附两种代码引以为戒!!!


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

const int maxn = 2e5 + 10;

struct data{
	int v;
	bool operator < (const data &b) const {
		return v < b.v;	
	}
};

struct WP{
	int t,v;
	bool operator < (const WP &b) const {
		return t > b.t;
	}
}w[maxn];

int n,i,j,ans = 0;

priority_queue <data> q;

int main()
{
	#ifndef YZY
		freopen("game.in","r",stdin);
		freopen("game.out","w",stdout);
	#else
		freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> n;
	for (i = 1; i <= n; i++) scanf("%d%d",&w[i].t,&w[i].v);
	sort (w + 1,w + n + 1);
	j = 1;
	for (i = 200000; i > 0; i--) {
		while (w[j].t == i && j <= n) q.push((data){w[j++].v});
		if (!q.empty()) {
			ans += q.top().v;
			q.pop();
		} 
	}
	cout << ans;
	return 0;
}



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

const int maxn = 2e5 + 10;

struct WP{
	int t,v;
	bool operator < (const WP &b) const {
		return v > b.v;
	}
}w[maxn];

int c[4*maxn],n,i,j,ans = 0,qr;

void build_tree(int o,int l,int r)
{
	if (l == r) {
		c[o] = 1;
		return;
	}
	
	int mid = (l + r) >> 1;
	build_tree(2*o,l,mid);
	build_tree(2*o+1,mid+1,r);
	c[o] = c[2*o] + c[2*o+1];
}

int query(int o,int l,int r)
{
	if (l == r) return l;
	int mid = (l + r) >> 1;
	int ret = -1;
	if (qr > mid) {
		if (c[2*o+1] >= 1) ret = query(2*o+1,mid+1,r);
		if (c[2*o] >= 1 && ret == -1) ret = query(2*o,l,mid);
	}
	else {
		if (c[2*o] >= 1) ret = query(2*o,l,mid);
	}
	return ret; 
}

void Modify(int o,int l,int r,int pos)
{
	--c[o];
	if (l == r) return;
	int mid = (l + r) >> 1;
	if (pos <= mid) Modify(2*o,l,mid,pos);
	else Modify(2*o+1,mid+1,r,pos);
}

int main()
{
	#ifndef YZY
		freopen("game.in","r",stdin);
		freopen("game.out","w",stdout);
	#else
		freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> n;
	for (i = 1; i <= n; i++) scanf("%d%d",&w[i].t,&w[i].v);
	sort (w + 1,w + n + 1);
	build_tree(1,1,200000);
	for (i = 1; i <= n; i++) {
		qr = w[i].t;
		int pos = query(1,1,200000);
		if (pos == -1) continue;
		ans += w[i].v;
		Modify(1,1,200000,pos);
	}
	cout << ans;
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值