Codeforce 1260 D.A Game with Traps(二分+貪心)

題目鏈接:https://codeforces.com/contest/1260/problem/D

題目大意:

一個長度爲n+1的直線上有k個陷阱,每個陷阱描述爲{l,r,v},表示這個陷阱的起始點l,終止點r,力量值v,你有m個士兵,每個士兵有一個能力值ai,當ai<vi時表示士兵i不能越過陷阱i,但是你可以走過去,當你經過位置ri時,陷阱i就消失了,初始時你們都在位置0,現在要去位置n+1,你現在必須選擇一些士兵,你攜帶着他們通過所有的障礙到達n+1,且必須在規定的時間t內完成,注意,如果想讓士兵移動,你必須和士兵在同一位置,也就是你清除了障礙物ri,你必須回到li-1帶上你的軍隊一起出發,問你最後能帶的最多的士兵的數量。

思路:

二分帶的最小的士兵能力值mid,然後驗證是否能在t時間內送過去。

顯然,如果沒有陷阱,我肯定帶着軍隊一起走最優,如果有陷阱,我肯定先把當前這個陷阱排除掉,再回去帶着軍隊走,這樣肯定最優(畫畫圖就知道了)。

所以,我們將陷阱按照左端點排序,如果陷阱i和陷阱i+1有重合,那麼我肯定只要從li走到max(ri,ri+1)就好了,否則我們就正常的走,這就是個簡單模擬過程。

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

const int maxn=2e5+10;
int a[maxn];
int l[maxn],r[maxn],d[maxn];
int m,n,k,t;
bool judge(int mid){
    int mx=a[mid];
    set<pair<int,int> >st;
    for(int i=1;i<=k;i++){
        if(d[i]>mx){
            st.insert({l[i],r[i]});
        }
    }
    int cur=0;
    int tim=0;
    for(auto it=st.begin();it!=st.end();it++){
        auto now=*it;
        if(now.first<=cur){//如果當前陷阱位置在位置的後面,繼續往前走
            tim=tim+max(0,now.second-cur);
            cur=max(cur,now.second);
        }
        else{
            //否則我必須走到下一個陷阱的前面去
            tim=tim+now.second-now.first+1;
            cur=now.second;
        }
    }
    tim=tim*2+n+1;
    return tim<=t;
}
signed 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+m+1);
    for(int i=1;i<=k;i++){
        scanf("%d%d%d",&l[i],&r[i],&d[i]);
    }
    int l=1,r=m;
    int ans=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(judge(mid)){
            ans=m-mid+1;
            r=mid-1;
        }
        else{
            l=mid+1;
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章