zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    搭建ARL资产安全灯塔
    免杀技术发展史
    米酷CMS 7.0.4代码审计
    腾讯安全实习 应用运维安全面试
    Docker部署CTF综合性靶场,定时刷新环境
    西湖论剑2020MISC-Yusa_yyds
    (转)马云炮轰银行监管的解读
    ATT&CK 实战
    Docker环境复现利用Redis未授权访问漏洞 >> 批量扫描检测利用
    修改CH340芯片信息
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10357635.html
Copyright © 2011-2022 走看看