A Game with Traps(CodeForces - 1260D )

题目链接:https://codeforces.com/problemset/problem/1260/D

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

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

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

You have tt 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 xx, you may move to x+1x+1 or x1x−1. This action consumes one second;
  • if your location is xx and the location of your squad is xx, you may move to x+1x+1 or to x1x−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 didi greater than agility of some soldier from the squad). This action consumes one second;
  • if your location is xx and there is a trap ii with ri=xri=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 00 to the point n+1n+1 (where the boss waits) in no more than tt seconds.

Input

The first line contains four integers mm, nn, kk and tt (1m,n,k,t21051≤m,n,k,t≤2⋅105, n<tn<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 mm integers a1a1, a2a2, ..., amam (1ai21051≤ai≤2⋅105), where aiai is the agility of the ii-th soldier.

Then kk lines follow, containing the descriptions of traps. Each line contains three numbers lili, riri and didi (1lirin1≤li≤ri≤n, 1di21051≤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 tt 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 33, 44 and 55 with you. The course of action is as follows:

  • go to 22 without your squad;
  • disarm the trap 22;
  • go to 33 without your squad;
  • disartm the trap 33;
  • go to 00 without your squad;
  • go to 77 with your squad.

The whole plan can be executed in 1313 seconds.

题目大意:

现在,你要带着t的时间内带着士兵到老板面前,你目前的可位置被视为0,老板的位置可被视为n+1;你有m个士兵,每个士兵都有对应的敏捷度,途中一共有k个陷阱,位于li处,当敏捷度低于di的士兵经过时会死亡,你不会受陷阱的影响,而且当你走到ri的位置时,可以解除第i个陷阱;每秒钟你最多只能走一个单位距离(向前或向后),士兵如果要前进,就必须和你同时前进,求最多能带几个士兵过关;
思路:贪心+二分

这里说一下贪心的思路,有两种情况:一种我们拆完炸弹之后接着拆,不回去接士兵,另一种我们拆完炸弹之后回去接士兵,再一起走 

通过画图我们可以很清楚的发现,

如果下一个炸弹所在的位置在自己的位置前面,并且拆除位置在我们后面,我们必须先去拆除炸弹,而不是去接士兵

相反,如果下一个炸弹的位置在自己前面,并且拆除位置也在我们前面,或者全都在我们后面,肯定先去接士兵

上面就是贪心的思想,只是我们怎么处理这两种情况呢?  直接暴力判断下一个位置吗,其实这样也不好处理

我们的目的就是尽可能的少花时间,不管我们是上面说的哪一种情况,都是保证某个区间最多都三遍,而不多走,这样就好处理了 ,用差分数组存一下哪个区间需要拆炸弹的

这个区间就是走三遍的,这样一下就处理好了 ,真的很精妙

看代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<list>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn=2e5+5;
const int maxm=100000+10;
const ull base=2333;
const LL INF=1e18;
int a[maxn],b[maxn];
int d[maxn],f[maxn];
int M,N,K,T;
struct Node
{
    int l,r,d;
}c[maxn];
bool judge(int x)
{
    for(int i=1;i<=N+1;i++) d[i]=f[i]=0;//差分数组 存下哪些区间需要走两遍
    int v=a[x];
    int sum=0;
    for(int i=1;i<=K;i++)
    {
        if(c[i].d>v)
        {
            d[c[i].l]++;
            d[c[i].r+1]--;
        }
    }
    for(int i=1;i<=N+1;i++)
    {
        f[i]=f[i-1]+d[i];
    }
    for(int i=1;i<=N+1;i++)//哪些区间需要走重复走的
    {
        if(f[i]>=1) sum++;
    }
    sum=sum*2+N+1;
    return sum<=T;
}
int main()
{
    scanf("%d%d%d%d",&M,&N,&K,&T);
    for(int i=1;i<=M;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=K;i++)
    {
        scanf("%d%d%d",&c[i].l,&c[i].r,&c[i].d);
    }
    sort(a+1,a+M+1);
    int l=1,r=M;//
    int ans=0;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(judge(mid))
        {

            ans=mid;
//            cout<<"b[mid]:"<<b[mid]<<" ans:"<<ans<<endl;
            r=mid-1;
        }
        else l=mid+1;
    }
    if(ans==0) printf("0\n");
    else printf("%d\n",M-ans+1);

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/caijiaming/p/11973018.html