zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Mac OS X系统下编译运行C代码
    Android intent传递list或对象
    Android中实现自定义的拍照应用
    由闭包引起的对javascript代码可维护性的思考
    让浏览器非阻塞加载javascript的几种方式
    Javascript中正则表达式的全局匹配模式
    解读JavaScript代码 var ie = !-[1,]
    Javascript中闭包的作用域链
    WPF代码注意事项,开发常见问题,知识总结
    WPF绑定各种数据源之object数据源
  • 原文地址:https://www.cnblogs.com/pandaking/p/12033891.html
Copyright © 2011-2022 走看看