Codeforces1260D (简单二分)

题意:有m个士兵,t秒,你要带尽可能多的士兵从0去n+1,且他们不能被杀死。路上有一些陷阱,陷阱d[i]会杀死能力比它小的士兵,陷阱位置在l[i],当你走到r[i]时可以拆除它。每次你可以向左或者向右移动。自己不会被陷阱杀死,可以先去把陷阱拆除再回来带兵。

              (1): 首先一个很简单的想法是带ai[i]大的士兵,这样的话比带ai[i]小的士兵更划算,这个应该想想就可以知道。

              (2):   因为这个显然是具有单调性的,带前l+1个士兵所要花的时间肯定是要大于等于这个带前l个士兵所要花的时间的。所以这样我们就可以知道f(l)(l为带前l个士兵)在l这个变量上花的时间是不下降的,那么我们就可以用二分来做,这个其实也是很显然的,二分单调性解决        (有时候很难真正的去解释,只能说题感觉)

              (3):   那么接下来回到一个新的问题,当我们带了这么多兵以后,怎么验证呢?这就是一个很简单的区间覆盖问题了,o(n)可以解决

下面是代码:

               

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <bitset>
 4 #include <algorithm>
 5 #include <iostream>
 6 typedef long long ll;
 7 using namespace std;
 8 const int maxn=201000;
 9 int m,n,k,t;
10 int ai[maxn];
11 struct node{
12     int li,ri,wi;
13 };
14 node sum[maxn];
15 
16 bool cmp(node n1,node n2){
17     return n1.li<n2.li;
18 }
19 
20 bool scmp(int a,int b){
21     return a>b;
22 }
23 
24 void init(){
25     scanf("%d%d%d%d",&m,&n,&k,&t);
26     for(int i=1;i<=m;i++) scanf("%d",&ai[i]);
27     sort(ai+1,ai+m+1,scmp);
28     for(int i=1;i<=k;i++) scanf("%d%d%d",&sum[i].li,&sum[i].ri,&sum[i].wi);
29     sort(sum+1,sum+k+1,cmp);
30 }
31 
32 bool check(int mid){
33     //如果没有人,直接返回true;
34     if(mid==0) return true;
35     //这个边界处理是大问题
36     //最后一个在循环外算
37     int res=0,l=-1,r=-1;
38     for(int i=1;i<=k;i++){
39        if(sum[i].wi<=ai[mid]) continue;
40        if(l==-1){ l=sum[i].li;r=sum[i].ri;continue; }
41        if(sum[i].li<=r){
42            r=max(sum[i].ri,r);
43        }else{
44            res+=(r-l+1);
45            r=sum[i].ri;l=sum[i].li;
46        }
47     }
48     //这个是在循环外算的
49     //if(l!=-1) 是为了防止没有经过运算就输出
50     if(l!=-1) res+=(r-l+1);
51     return res*2+(n+1)<=t;
52 }
53 
54 void solve(){
55     //二分边界不要设错了,不要设错了!!!!!!!!
56     int lb=0,rb=m,ans=1;
57     while(lb<=rb){
58         int mid=(lb+rb)/2;
59         if(check(mid)){
60             ans=mid;
61             lb=mid+1;
62         }else rb=mid-1;
63     }
64     printf("%d
",ans);
65 }
66 
67 int main(){
68     //读入数据
69     init();
70     //处理
71     solve();
72     return 0;
73 }
View Code
原文地址:https://www.cnblogs.com/pandaking/p/12033891.html