Educational Codeforces Round 77 (Rated for Div. 2) D A game with traps

题意:
x正轴上有着一个陷阱的位置,开关和灵敏度,如果一个士兵灵敏度输给陷阱,他是过不去这个陷阱的
幸运的是,你可以先过去把开关给关了,没错你是不怕陷阱的
接下来呢你有操作,你移动一个,耗费一秒
而你的团队需要你一起才能移动,但是团队有一个士兵过不了,那就不能过去,你可以先过去关掉开关,然后再回来带领你的团队过去
思路:
一开始就想到二分找最多人数,然后贪心来走路满足t秒内。
问题是怎么贪心呢?
我们不难发现我们关完开关后再回到队伍里一起走,所以我们要尽可能的减少这种往回。
图书一画图就发现,我们以陷进位置和开关位置连起来看作一个线段,两个线段相交,答案贡献就是2*(关掉第一个后顺手关第二个)
线段不相交就发现,例如(2,3)(5,10)你当然不可以关完3后还去关10,因为这样你就沙雕了,你回来的时候又通过来3 5,这是没必要的
所以对于不是相交的,我们走到3后就不用顺手帮5走到10了。

#include<bits/stdc++.h>
using namespace std;
const int maxx=2e5+10;
int l[maxx],r[maxx],d[maxx],a[maxx];
int n,m,k,t;
vector<pair<int,int> >v[maxx];
int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
bool cmp(int a,int b){return a>b;}
int work(int x) {
    int tmpp=1,pre=0;// printf("hhx :: %d\n",x);
    for(int i=1;i<=n;i++) {
        int maxx=-1;
//        for(vector<pair<int,int> >::iterator it=v[i].begin();it!=v[i].end();it++)
    for(auto it:v[i])
            if(it.second>x) maxx=max(maxx,it.first);
        if(~maxx) {
            pre=max(pre,i-1);
            if(pre<maxx) tmpp+=2*(maxx-pre),pre=maxx;
        }
        tmpp++;
        // printf("%d %d\n",i,x);
            printf("tmp=%d\n",tmpp);
        if(tmpp>t) return 0;
    }
    return 1;
}


int main()
{
    int ans=0;
    m=read(),n=read(),k=read(),t=read();
    for(int i=1;i<=m;i++) a[i]=read();
    a[0]=0x3f3f3f3f;
    for(int i=1;i<=k;i++){
        l[i]=read();r[i]=read();d[i]=read();
        v[l[i]].push_back(make_pair(r[i],d[i]));
    }
    int l=0,r=m;
    sort(a+1,a+1+m,cmp);
    work(a[1]);
    while(l<=r){
        int mid=(l+r)/2;
        if(work(a[mid])) ans=mid,l=mid+1;
        else r=mid-1;
    }
    printf("%d\n",ans);
}

  

原文地址:https://www.cnblogs.com/hgangang/p/11960410.html