A Game with Traps CodeForces - 1260D(二分+贪心)

You are playing a computer game, where you lead a party of m soldiers. Each soldier is characterised by his agility ai.

The level you are trying to get through can be represented as a straight line segment from point 0 (where you and your squad is initially located) to point n+1 (where the boss is located).

The level is filled with k traps. Each trap is represented by three numbers li, ri and di. li is the location of the trap, and di is the danger level of the trap: whenever a soldier with agility lower than di steps on a trap (that is, moves to the point li), he gets instantly killed. Fortunately, you can disarm traps: if you move to the point ri, you disarm this trap, and it no longer poses any danger to your soldiers. Traps don’t affect you, only your soldiers.

You have t seconds to complete the level — that is, to bring some soldiers from your squad to the boss. Before the level starts, you choose which soldiers will be coming with you, and which soldiers won’t be. After that, you have to bring all of the chosen soldiers to the boss. To do so, you may perform the following actions:

if your location is x, you may move to x+1 or x−1. This action consumes one second;
if your location is x and the location of your squad is x, you may move to x+1 or to x−1 with your squad in one second. You may not perform this action if it puts some soldier in danger (i. e. the point your squad is moving into contains a non-disarmed trap with di greater than agility of some soldier from the squad). This action consumes one second;
if your location is x and there is a trap i with ri=x, you may disarm this trap. This action is done instantly (it consumes no time).
Note that after each action both your coordinate and the coordinate of your squad should be integers.

You have to choose the maximum number of soldiers such that they all can be brought from the point 0 to the point n+1 (where the boss waits) in no more than t seconds.

Input
The first line contains four integers m, n, k and t (1≤m,n,k,t≤2⋅105, n<t) — the number of soldiers, the number of integer points between the squad and the boss, the number of traps and the maximum number of seconds you may spend to bring the squad to the boss, respectively.

The second line contains m integers a1, a2, …, am (1≤ai≤2⋅105), where ai is the agility of the i-th soldier.

Then k lines follow, containing the descriptions of traps. Each line contains three numbers li, ri and di (1≤li≤ri≤n, 1≤di≤2⋅105) — the location of the trap, the location where the trap can be disarmed, and its danger level, respectively.

Output
Print one integer — the maximum number of soldiers you may choose so that you may bring them all to the boss in no more than t seconds.

Example
Input
5 6 4 14
1 2 3 4 5
1 5 2
1 2 5
2 3 5
3 5 3
Output
3
Note
In the first example you may take soldiers with agility 3, 4 and 5 with you. The course of action is as follows:

go to 2 without your squad;
disarm the trap 2;
go to 3 without your squad;
disartm the trap 3;
go to 0 without your squad;
go to 7 with your squad.
The whole plan can be executed in 13 seconds.
很不错的一道题,很考验思维。很明显我没有通过考验。
思路:二分答案,去判断是否符合题意。我们在判断的时候,只需要看当前最小值就可以了。例如,我们现在判断x个人是否可以通过,我们只需要看这x人中最小的一个就行了。如果当前l有陷阱并且这个陷阱会阻止我们通过,那么我们就先走到l-1,然后“我”再去踩陷阱。我们将陷阱按照位置排序之后,找出会对我们有阻碍的陷阱,然后遍历,求出踩陷阱应该花费的时间,乘以2,再加上本应该走的时间n+1就可以了。
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=2e5+100;
struct node{
	int l,r,v;
	bool operator<(const node &a)const{
		return l<a.l;//按照位置排序,因为本身时间就与位置有关。
	}
}p[maxx];
int a[maxx];
vector<int> q[maxx];
int m,n,k,t;

inline bool check(int kl)
{
	if(kl==0) return 1;
	int mv=a[m-kl+1];
	ll ans=0;
	node c[k+2];
	int cnt=0;
	for(int i=1;i<=k;i++) if(p[i].v>mv) c[++cnt]=p[i];
	int _max=0;
	for(int i=1;i<=cnt;i++)
	{
		if(c[i].r<=_max) continue;//这代表着当前这个陷阱已经被我们解除过了。
		_max=max(_max,c[i].l-1);//这代表着我们走到了能走的最大值。
		ans+=(ll)(c[i].r-_max);//这代表着我们踩陷阱花费的时间。
		_max=c[i].r;
	}
	ans=ans*2ll+n+1;//ans*2,因为要往返。
	return ans<=(ll)t;
}
int main()
{
	scanf("%d%d%d%d",&m,&n,&k,&t);
	for(int i=1;i<=m;i++) scanf("%d",&a[i]);
	sort(a+1,a+1+m);
	for(int i=1;i<=k;i++) scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].v);
	sort(p+1,p+1+k);
	int ans=0;
	int l=0,r=m;
	while(l<=r)
	{
		int mid=l+r>>1;
		if(check(mid))
		{
			ans=max(ans,mid);
			l=mid+1;
		}
		else r=mid-1;
	}
	cout<<ans<<endl;
	return 0;
}

很好的一道题目!!
努力加油a啊,(o)/~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starlet_kiss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值