zoukankan      html  css  js  c++  java
  • 1178: [Apio2009]CONVENTION会议中心

    1178: [Apio2009]CONVENTION会议中心

    https://lydsy.com/JudgeOnline/problem.php?id=1178

    分析:

      set+倍增。

      首先把所有有包含的去掉,只保留包含的最小的边(如果两条线段中的一条包含另一条,那么保留被包含的)然后此时就可以直接贪心了。直接从一条边找不想交的下一条边。然后就行了(因为此时没有包含的,左端点递增,右端点递增)。

      因为每条边的下一条是唯一的,那么可以倍增维护往后走2^i步,到的点。此时可以快速知道任意一段区间的最多可以有多少条边了。

      因为要字典序最小,从编号小的可以是枚举,如果这条边[l,r]可以加进去。tl,tr如下图所示。

      那么[l,r]可以加入的条件是,calc(tl+1,tr-1)=calc(tl+1,l-1)+calc(r+1,tr-1)+1,calc(l,r)表示l~r最多可以放几条线段。

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<cctype>
     7 #include<set>
     8 #include<queue>
     9 #include<vector>
    10 #include<map>
    11 using namespace std;
    12 typedef long long LL;
    13 
    14 inline int read() {
    15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    17 }
    18 
    19 const int N = 200005;
    20 const int INF = 1e9;
    21 const int Log = 20;
    22 
    23 struct Edge{
    24     int l, r;
    25     Edge() { }
    26     Edge(int a,int b) { l = a, r = b; }
    27     bool operator < (const Edge &A) const {
    28         return r == A.r ? l > A.l : r < A.r;
    29     }
    30 }A[N], ori[N]; 
    31 int disc[N << 1], f[N][Log + 1], X[N], Y[N], m = 1;
    32 set<Edge>s;
    33 
    34 int Calc(int l,int r) {
    35     int p = lower_bound(X + 1, X + m + 1, l) - X, ans = 1; // ans=1!!!
    36     if (Y[p] > r || p > m) return 0;
    37     for (int i = Log; i >= 0; --i) 
    38         if (f[p][i] && Y[f[p][i]] <= r) 
    39         ans += (1 << i), p = f[p][i];
    40     return ans;
    41 }
    42 
    43 int main() {
    44     int n = read();
    45     for (int i = 1; i <= n; ++i) {
    46         A[i].l = read(), A[i].r = read();
    47         disc[i] = A[i].l, disc[i + n] = A[i].r;
    48     }
    49     sort(disc + 1, disc + n + n + 1);
    50     int cnt = 1;
    51     for (int i = 2; i <= n + n; ++i) if (disc[i] != disc[cnt]) disc[++cnt] = disc[i];
    52     for (int i = 1; i <= n; ++i) {
    53         A[i].l = lower_bound(disc + 1, disc + cnt + 1, A[i].l) - disc;
    54         A[i].r = lower_bound(disc + 1, disc + cnt + 1, A[i].r) - disc;
    55         ori[i] = A[i];
    56     }
    57     sort(A + 1, A + n + 1);
    58     X[m] = A[m].l, Y[m] = A[m].r;
    59     for (int i = 2; i <= n; ++i) 
    60         if (A[i].l > A[m].l) A[++m] = A[i], X[m] = A[m].l, Y[m] = A[m].r;
    61     for (int i = 1, j = 1; i <= m; ++i) {
    62         while (j <= m && A[j].l <= A[i].r) j ++;
    63         if (j <= m) f[i][0] = j;
    64     }
    65     for (int j = 1; j <= Log; ++j) 
    66         for (int i = 1; i <= m; ++i) f[i][j] = f[f[i][j - 1]][j - 1];
    67     
    68     int ans = Calc(-INF, INF);
    69     cout << ans << "
    ";
    70      
    71     s.insert(Edge(INF, INF));
    72     s.insert(Edge(-INF, -INF));
    73     
    74     int now = 0;
    75     for (int i = 1; i <= n; ++i) {
    76         set<Edge> :: iterator x = s.lower_bound(ori[i]), y = x; y --; // 端点没有重复的,可以直接set的lower_bound 
    77         int tl = y->r, tr = x->l, l = ori[i].l, r = ori[i].r;
    78         if (tl >= l || tr <= r) continue;
    79         if (Calc(tl + 1, tr - 1) == Calc(tl + 1, l - 1) + Calc(r + 1, tr - 1) + 1) {
    80             if (++now == ans) return printf("%d",i), 0;
    81             else printf("%d ",i);
    82             s.insert(ori[i]);
    83         }
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    Redis基础学习(三)—Key操作
    Redis基础学习(二)—数据类型
    Redis基础学习(一)—Redis的安装
    Bootstrap基础学习(二)—表单
    Bootstrap基础学习(一)—表格与按钮
    List去除重复的元素
    jQuery 将表单序列化为Json对象
    SpringMVC基础学习(三)—参数绑定
    CentOS 7.1安装Elasticsearch和Storm
    Python多线程中join函数与setDaemon函数使用说明
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10038054.html
Copyright © 2011-2022 走看看