• p3634 [APIO2012]守卫


    传送门

    分析

    1.先预处理出不被0覆盖的点,然后对每个点处理出在它左边离他最近的点和在他右边理他最近的点。

    2.对于每个至少存在一个忍者的区间,先将它左右边界处理为不被0所覆盖。排序后将包含其他区间的区间去除。

    3.贪心求出前i个区间最小忍者数和后i个区间最小忍者数。

    4.我们知道对于一个区间除了点R[i]之外最优的点就是R[i]-1,所以我们二分一个右端点小于R[i]-1的最靠右区间k1和一个左端点大于R[i]-1的最靠左区间k2,如果f[k1]+g[k2]+1>k则代表点R[i]必选

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    struct node {
        int le,ri,k;
    };
    node d[110000];
    int a[110000],b[110000],pos[110000],sum[110000],cnt,tot,n,m,k;
    int L[110000],R[110000],f[110000],g[110000];
    inline bool cmp(const node x,const node y){
        return x.le<y.le;
    }
    int main(){
        int i,j;
        scanf("%d%d%d",&n,&k,&m);
        for(i=1;i<=m;i++){
          scanf("%d%d%d",&d[i].le,&d[i].ri,&d[i].k);
          if(!d[i].k){
              sum[d[i].le]++;
              sum[d[i].ri+1]--;
          }
        }
        for(i=1;i<=n;i++){
          sum[i]+=sum[i-1];
          if(!sum[i]){
              pos[++tot]=i;
              a[i]=b[i]=tot;
          }
        }
        if(tot==k){
          for(i=1;i<=tot;i++)
            printf("%d
    ",pos[i]);
          return 0;
        }
        a[n+1]=n+1;
        for(i=n;i>0;i--)
          if(!a[i])a[i]=a[i+1];
        for(i=1;i<=n;i++)
          if(!b[i])b[i]=b[i-1];
        for(i=1;i<=m;i++)
          if(d[i].k){
              d[++cnt].le=a[d[i].le];
              d[cnt].ri=b[d[i].ri];
          }
        m=cnt;
        sort(d+1,d+m+1,cmp);
        cnt=0;
        for(i=1;i<=m;i++){
          while(cnt&&d[i].le>=L[cnt]&&d[i].ri<=R[cnt])--cnt;
          L[++cnt]=d[i].le;
          R[cnt]=d[i].ri;
        }
        int l=n+1,r=0;
        for(i=1;i<=cnt;i++){
          if(L[i]>r)f[i]=f[i-1]+1,r=R[i];
            else f[i]=f[i-1];
        }
        for(i=cnt;i>0;i--){
          if(R[i]<l)g[i]=g[i+1]+1,l=L[i];
            else g[i]=g[i+1];
        }
        int ok=0;
        for(i=1;i<=cnt;i++){
          if(f[i]==f[i-1])continue;
          if(L[i]==R[i]){
              printf("%d
    ",pos[R[i]]);
              ok=1;
              continue;
          }
          int l=0,r=cnt+1,x=0,y=cnt+1;
          while(r-l>1){
              int mid=(l+r)>>1;
              if(R[mid]<R[i]-1)x=mid,l=mid;
                else r=mid;
          }
          l=0,r=cnt+1;
          while(r-l>1){
              int mid=(l+r)>>1;
              if(L[mid]>R[i]-1)y=mid,r=mid;
                else l=mid;
          }
          if(f[x]+g[y]+1>k){
              printf("%d
    ",pos[R[i]]);
              ok=1;
          }
        }
        if(!ok)puts("-1");
        return 0;
    }
  • 相关阅读:
    BUAA面向对象第一单元作业总结
    Kafka 总结学习
    Mybatis学习-GetMybatisInMyHead
    大数据实战-电信客服-重点记录
    基于有穷状态机思想的电梯系统
    Selective Search-目标检测“垫脚石”
    SparkSQL 实验
    Spark Core实验
    MapReduce实验
    NoSQL实验
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10357635.html
Copyright © 2020-2023  润新知