Educational Codeforces Round 77 D. A Game with Traps 二分答案+前缀和

http://codeforces.com/contest/1260/problem/D

题意:

你m个士兵,每个士兵都有敏捷值

有k个陷阱,每个陷阱有3个属性:l,r,dangerous,其中:

l:若你的士兵敏捷值小于dangerous,那么你带领士兵经过这个点就会当场去世

r:为了避免你的士兵当场去世,你可以先自己走到r点,此时陷阱就会失效

士兵必须跟着你一起走,你可以先选择自己去破坏陷阱,然后回来带着士兵走

你的任务是带领士兵从0点走到n+1这个点,你每走一格就会花费1s

问:在t秒内(包括t秒),你最多能带多少个士兵前往n+1这个点

 

 

 

题解:

首先士兵应该要按灵活值排序,灵活值高的士兵优先带

下面只考虑危险值大于所带士兵最小灵活性的陷阱

销毁陷阱大概有3种方法:

1.对于每个陷阱都先自己走到r销毁,然后倒过来带士兵走

2.先一次性将所有陷阱踩完,然后带着士兵一次性通过

前面两种方法都不是最优

比如对于这3个陷阱 

L1= 2   R1= 5

L2= 4   R2= 6

L3= 8   R3= 9

两种走法分别:

 

走法1: 32s  走法2: 27s

还有一种走法:

第三种走法就是:

对于l,r有重叠的区间,看成一个大区间,一次性走完,然后分别走完各个大区间

 

使用区间前缀和处理区间叠加问题

然后二分答案即可

#include<bits/stdc++.h>
#define ll long long 
#define ull unsigned long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 7;
int n, m, k, t;
int num[maxn], flag[maxn];
struct node {
	int l, r, v;
}trap[maxn];
bool cmp(int a, int b) {
	return a > b;
}
bool check(int rk) {
	for (int i = 1; i <= k; i++)
		if (trap[i].v > rk) { //区间前缀和
			flag[trap[i].l]++;
			flag[trap[i].r + 1]--;
		}
	int hav = 0, sum = 0;
	for (int i = 1; i <= n + 1; i++) {
		hav += flag[i];
		flag[i] = 0;//memset
		if (hav) //假如当前被区间覆盖,那么说明这个格子需要走3次
			sum += 3;
		else //否则带队一次过即可
			sum += 1;
	}
	if (sum <= t)
		return 1;
	else
		return 0;
}
int main() {
	cin >> m >> n >> k >> t;
	for (int i = 1; i <= m; i++)
		scanf("%d", num + i);
	sort(num + 1, num + 1 + m, cmp);//从大到小排序
	for (int i = 1; i <= k; i++)
		scanf("%d %d %d", &trap[i].l, &trap[i].r, &trap[i].v);
	int l = 0, r = m;
	while (l < r) { //二分答案
		int mid = (l + r + 1) >> 1;
		if (check(num[mid]))
			l = mid;
		else
			r = mid - 1;
	}
	cout << l << endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值