CF 1260 D 题解

发布于:2022-10-13 ⋅ 阅读:(563) ⋅ 点赞:(0)

原题链接:

Problem - 1260D - Codeforces

题意:

你有 m 个士兵,你和士兵都在 0 坐标上,你要把其中的某些士兵带到 n+1 的坐标去打 boss,过程中不能死,每个士兵都有敏捷度 a_i,其中有 k 个陷阱,每个陷阱的坐标在 l_i ,危险程度为 d_i (当士兵的敏捷度 < 陷阱的危险程度时,士兵将立即死亡),你可以到 r_i 去解除这个陷阱的威胁,你在 x 坐标可以做如下操作:

1:你走到 x-1 或 x+1 的坐标,花费一个单位时间。

2:你和你的士兵 走到 x-1 或 x+1 的坐标,花费一个单位时间。

3:如果 x = l_i ,你可以解除第 i 个陷阱。

(你和你的士兵可以不在同一个位置)

(陷阱的危险程度不会累加)

问你最多能带多少个士兵在 t 个单位时间内去打 boss。

解法:

二分答案。可以二分最多可以带的士兵数。右端点要设成 m + 1 (调了 1 h 就离谱)。

check 函数可以用一个变量来表示自己最远走到哪里,之后加上多走的就可以了。

Code :

 # include <bits/stdc++.h>
//# include "windows.h"
# define ll long long
//# define int ll
# define db double
# define mod 998244353
//# define mod 1000000007
# define inf 1000000000
# define INF 1000000000000000000
# define fi first
# define se second
# define pb push_back
using namespace std;
int dx[15] = {0, 0, 1, -1, -1, -1, 1, 1};
int dy[15] = {1, -1, 0, 0, -1, 1, -1, 1};
 
int n, m, k, t, b[200005];
 
vector <pii> g[200005];
 
bool cmp1(int a, int b){
	return a > b;
}
 
int chk(int x){
	int num = b[x], ret = 0, ind = 0;
	for (int i = 1;i <= n+1;i++){
		ind = max(ind, i-1);
		ret++;
		if (g[i].size() == 0) continue;
		for (pii a : g[i]){
			int r = a.fi, w = a.se;
			if (w > num){
				if (ind >= r || i-1 >= r) continue;
				ret += 2*(r - max(ind, i-1));
				ind = max(ind, r);
			}
		}
	}
	return (ret <= t);
}
 
int main(){
	scanf("%d%d%d%d", &m, &n, &k, &t);
	for (int i = 1;i <= m;i++) scanf("%d", &b[i]);
	for (int i = 1;i <= k;i++){
		int l, r, d;
		scanf("%d%d%d", &l, &r, &d);
		g[l].pb({r, d});
	} 
	sort (b+1, b+m+1, cmp1);
	int l = 0, r = m+1;
	if (chk(l+1)) l++; 
	while (l < r-1){
		int mid = (l+r) >> 1;
		if (chk(mid)) l = mid;
		else r = mid; 
	}
	printf("%d", l);
	return 0;
}

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到