zoukankan      html  css  js  c++  java
  • 解题:POI 2018 Prawnicy

    题面

    网上好像都是堆的做法啊......我这个不算离散化是$O(n)$的说(虽然有一坨vector可能不开O2会爆炸)

    题目即是让我们求是否存在一个最长的是不少于$k$个给出区间子集的区间,如果存在输出方案。我们发现当我们的左端点固定时,右端点越向右越可能不合法,但同时答案在不断扩大(好像不太严谨),这给了我们一个更新答案的条件;而当右端点固定左端点向右移动时,答案只会越来越合法同时越来越不优。这样我们就可以尺取做了,问题是如何统计当前区间是几个区间的子集呢?

    事实上这不需要任何数据结构,我们将每个区间拆成左右端点分别用vector存起来,同时开一个数组用来标记,然后当我们的指针遇到区间时讨论:

    如果左指针碰到左端点,检查一下这个区间的右端点是否在右指针右边,如果在且这个区间还没被标记,则标记它并记录贡献

    如果右指针扫过右端点(注意是扫过),检查一下这个区间是否被标记,如果被标记则移除它的贡献

    如果右指针碰到右端点,检查一下这个区间的左端点是否在左指针左边,如果在且这个区间还没被标记,则标记它并记录贡献

    这样如果不算离散化就是$O(n)$的辣

     1 #include<cstdio>
     2 #include<vector>
     3 #include<cstring>
     4 #include<utility>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=1000005;
     8 vector<pair<int,int> > ln[2*N],rn[2*N];
     9 int n,k,c,p1,p2,a1,a2,cnt,xnt,tot,ans;
    10 int ll[N],rr[N],uni[2*N],mark[N];
    11 void renew(int typ)
    12 {
    13     if(!typ)
    14     {
    15         for(int i=0;i<(int)ln[p1].size();++i)
    16             if(ln[p1][i].first>=p2) 
    17                 if(!mark[ln[p1][i].second])
    18                     mark[ln[p1][i].second]=true,xnt++;
    19     }
    20     else
    21     {
    22         for(int i=0;i<(int)rn[p2-1].size();i++)
    23             if(mark[rn[p2-1][i].second])
    24                 mark[rn[p2-1][i].second]=false,xnt--;
    25         for(int i=0;i<(int)rn[p2].size();i++)
    26             if(rn[p2][i].first<=p1)
    27                 if(!mark[rn[p2][i].second])
    28                     mark[rn[p2][i].second]=true,xnt++;
    29     }
    30 }
    31 int main ()
    32 {
    33     scanf("%d%d",&n,&k);
    34     for(int i=1;i<=n;i++)
    35     {
    36         scanf("%d%d",&ll[i],&rr[i]);
    37         uni[++tot]=ll[i],uni[++tot]=rr[i];
    38     }
    39     sort(uni+1,uni+1+tot),tot=unique(uni+1,uni+1+tot)-uni-1;
    40     for(int i=1;i<=n;i++)
    41     {
    42         ll[i]=lower_bound(uni+1,uni+1+tot,ll[i])-uni;
    43         rr[i]=lower_bound(uni+1,uni+1+tot,rr[i])-uni;
    44         ln[ll[i]].push_back(make_pair(rr[i],i));
    45         rn[rr[i]].push_back(make_pair(ll[i],i));
    46     }
    47     p1=p2=0; 
    48     while(p1<=tot&&p2<=tot)
    49     {
    50         if(p1>p2) p2=p1,renew(1); 
    51         if(xnt>=k) 
    52         {
    53             while(xnt>=k&&p2<=tot) p2++,renew(1); 
    54             if(uni[p2-1]-uni[p1]>ans) ans=max(ans,uni[p2-1]-uni[p1]),a1=p1,a2=p2-1; 
    55         }
    56         p1++,renew(0);
    57     }
    58     printf("%d
    ",ans); 
    59     for(int i=1;i<=n&&c<k;i++)
    60         if(ll[i]<=a1&&rr[i]>=a2)
    61             printf("%d ",i),c++;
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    SQOOP的安装配置_Linux伊甸园开源社区24小时滚动更新开源资讯,全年无休!
    Cloudera's Hadoop Demo VM for CDH4 Cloudera Support
    海量文档查同或聚类问题 Locality Sensitive Hash 算法
    part 1: resemblance with the jaccard coefficient
    计算机科学中最重要的32个算法zz
    详细的tfidf构建过程实例(转)
    2012 Beijing Google Dev FastDay(11/03/2012) 移动新观察
    百度技术沙龙
    Hive官方手册翻译(Getting Started) 实践检验真理 51CTO技术博客
    《周末休闲吧》:教你如何玩车震——车震全程攻略!_周末休闲吧_百度空间
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/9861471.html
Copyright © 2011-2022 走看看