zoukankan      html  css  js  c++  java
  • [bzoj1178]会议中心

    考虑用f[i][j]表示以i为起点(i是时间,所以要离散)选$2^j$条线段(这里不是时间)最小的终点,预处理用倍增的方式来求即可
    预处理出这个数组后,就可以很快的求出在$[l,r]$的时间内最多能选多少条线段,类似于树上的倍增(注意判断超过最大时间的情况)
    然后从前往后枚举每一段时间,考虑能否加入,当且仅当其分割的那个区间的两部分的答案之和+1=原区间的答案,找区间可以用两个set(分别维护起点和终点)来搞

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 200005
     4 struct ji{
     5     int l,r;
     6     bool operator < (const ji &k)const{
     7         return (l<k.l)||(l==k.l)&&(r<k.r);
     8     }
     9 }a[N],aa[N];
    10 set<int>s1,s2;
    11 int n,m,b[N<<1],f[N<<1][21];
    12 void build(){
    13     memcpy(aa,a,sizeof(a));
    14     sort(aa+1,aa+n+1);
    15     aa[n+1].l=aa[n+1].r=m+1;
    16     for(int i=1,j=1;i<=m;i++){
    17         while (i>aa[j].l)j++;
    18         f[i][0]=aa[j].r;
    19     }
    20     for(int i=m-1;i;i--)f[i][0]=min(f[i][0],f[i+1][0]);
    21     for(int i=0;i<=20;i++)f[m+1][i]=m+1;
    22     for(int j=1;j<=20;j++)
    23         for(int i=1;i<=m;i++)f[i][j]=f[min(m,f[i][j-1])+1][j-1];
    24 }
    25 int query(int l,int r){
    26     int ans=0;
    27     for(int i=20;i>=0;i--)
    28         if (f[l][i]<=r){
    29             l=min(m,f[l][i])+1;
    30             ans+=(1<<i);
    31         }
    32     return ans;
    33 }
    34 int main(){
    35     scanf("%d",&n);
    36     for(int i=1;i<=n;i++){
    37         scanf("%d%d",&a[i].l,&a[i].r);
    38         b[++b[0]]=a[i].l;
    39         b[++b[0]]=a[i].r;
    40     }
    41     sort(b+1,b+2*n+1);
    42     m=unique(b+1,b+2*n+1)-b-1;
    43     for(int i=1;i<=n;i++){
    44         a[i].l=lower_bound(b+1,b+m+1,a[i].l)-b;
    45         a[i].r=lower_bound(b+1,b+m+1,a[i].r)-b;
    46     }
    47     build();
    48     printf("%d
    ",query(1,m));
    49     bool flag=0;
    50     s1.insert(1);
    51     s2.insert(m);
    52     for(int i=1;i<=n;i++){
    53         if ((!s1.size())||(*s1.begin()>a[i].l)||(*--s2.end()<a[i].r))continue;
    54         int x=*--s1.upper_bound(a[i].l),y=*s2.lower_bound(a[i].r);
    55         if ((x!=*--s1.end())&&(*s1.upper_bound(a[i].l)<=y))continue;
    56         if (query(x,y)==query(x,a[i].l-1)+1+query(a[i].r+1,y)){
    57             if (a[i].r==y)s2.erase(y);
    58             else s1.insert(a[i].r+1);
    59             if (a[i].l==x)s1.erase(x);
    60             else s2.insert(a[i].l-1);
    61             if (flag)printf(" ");
    62             flag=1;
    63             printf("%d",i);
    64         }
    65     }
    66 } 
    View Code
  • 相关阅读:
    新年新方向-斩获新职位
    专利之家:让灵感冒冒泡
    转帖:专利之家
    WPF:Localization 基础
    WPF教程.002
    有关XXX产品研发管理约定
    转帖:曲线路标北京前门上岗
    超出想象-超级终端显示器
    小e的每日一画 之 小男孩在太阳下敬礼 20080102
    小e的每日一画 之 飞毯旅行记 20071231
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/12212890.html
Copyright © 2011-2022 走看看