传送门


只有第一问就比较水了

每一次贪心地选择当前可以选择的所有线段中右端点最短的,排序之后扫一遍即可。

考虑第二问。按照编号从小到大考虑每一条线段是否能够被加入。假设当前选了一个区间集合\(T\),当前正在考虑第\(i\)个区间\((l_i,r_i)\)能否被加入。假如集合\(T\)中存在一个区间\((l_j,r_j)\)与\((l_i,r_i)\)有交,那么显然这个区间不能被放进去。

如果说不存在这样的区间,考虑集合\(T\)中区间\((l_i,r_i)\)的前驱\((l_p,r_p)\)和后继\((l_q,r_q)\)。那么\((l_i,r_i)\)能够被加入的充要条件是:\(f(r_p+1,l_i-1) + f(r_i+1 , l_q - 1) + 1 = f(r_p + 1 , l_q - 1)\),其中\(f(i,j)\)表示只选择被包含于区间\([i,j]\)的区间,最多能够选择多少个区间。

显然我们不能每一次\(O(n)\)地计算\(f\)函数,考虑其他的方法。

在所有区间中,去掉包含了其他区间的区间。那么这些区间按照左端点排序后,左端点递增,右端点也递增。我们在这样的区间上贪心时,就可以对所有区间扫一遍,每一次能选即选。

注意到选中了某一个区间之后,下一次选中的区间是固定的,故考虑倍增优化。

设\(jmp_{i,j}\)表示从第\(i\)个区间开始向右选择,选择到的\(2^j\)个区间的编号,不难使用双指针预处理。

接下来考虑计算\(f(l,r)\)。通过二分查找找到左端点\(\geq l\)的最左端的区间\(x\),那么如果\(r_x \leq r\),\(x\)一定是会被选中的。而选中\(x\)之后接下来贪心选择的所有区间都可以通过倍增知道。那么倍增找到接下来选择的所有区间中右端点\(\leq r\)的最右段的区间并记录总共经过多少个区间即可。

对于区间集合\(T\)可以使用\(set\)维护。值得注意的是std::lower_bound在set等不支持随机访问的STL下复杂度不正确,请使用std::set::lower_bound。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<vector>
#include<cmath>
#include<random>
//This code is written by Itst
using namespace std;

inline int read(){
    int a = 0;
    char c = getchar();
    while(!isdigit(c))
        c = getchar();
    while(isdigit(c)){
        a = a * 10 + c - 48;
        c = getchar();
    }
    return a;
}

const int MAXN = 2e5 + 3;
struct line{
    int l , r , ind;
    bool operator <(const line a)const{
        return l < a.l || l == a.l && r < a.r;
    }
}now[MAXN] , L[MAXN];
set < line > S;
set < line > :: iterator itS;
int N , cnt , cntL , jump[MAXN][21];

bool cmp(line a , line b){
    return a.ind < b.ind;
}

void init(){
    int minN = 1;
    sort(now + 1 , now + N + 1);
    for(int i = 1 ; i <= N ; ++i){
        if(now[minN].r < now[i].l){
            ++cnt;
            minN = i;
        }
        else
            if(now[minN].r > now[i].r)
                minN = i;
    }
    ++cnt;
    minN = 1e9;
    for(int i = N ; i ; --i)
        if(now[i].r < minN){
            minN = now[i].r;
            L[cntL++] = now[i];
        }
    reverse(L , L + cntL);
    int p = cntL - 1;
    for(int i = cntL - 1 ; i >= 0 ; --i){
        while(p > i && L[p].l > L[i].r)
            --p;
        jump[i][0] = p == cntL - 1 ? -1 : p + 1;
        for(int j = 1 ; j <= 19 ; ++j)
            jump[i][j] = jump[i][j - 1] == -1 ? -1 : jump[jump[i][j - 1]][j - 1];
    }
}

int query(int l , int r){
    int t = lower_bound(L , L + cntL , (line){l , 0}) - L;
    if(t == cntL || L[t].r > r)
        return 0;
    int sum = 0;
    for(int i = 19 ; i >= 0 ; --i)
        if(jump[t][i] != -1 && L[jump[t][i]].r <= r){
            sum += 1 << i;
            t = jump[t][i];
        }
    return sum + 1;
}

#define INF 2e9

int main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    N = read();
    for(int i = 1 ; i <= N ; ++i){
        now[i].l = read();
        now[i].r = read();
        now[i].ind = i;
    }
    init();
    printf("%d\n" , cnt);
    sort(now + 1 , now + N + 1 , cmp);
    for(int i = 1 ; i <= N && cnt ; ++i){
        int L , R;
        itS = S.lower_bound(now[i]);
        if(itS == S.end())
            R = INF;
        else
            if(itS->l > now[i].r)
                R = itS->l - 1;
            else
                continue;
        if(itS == S.begin())
            L = 0;
        else
            if((--itS)->r < now[i].l)
                L = itS->r + 1;
            else
                continue;
        if(query(L , now[i].l - 1) + query(now[i].r + 1 , R) + 1 == query(L , R)){
            printf("%d " , i);
            S.insert(now[i]);
            --cnt;
        }
    }
    return 0;
}

BZOJ1178 APIO2009 会议中心 贪心、倍增的更多相关文章

  1. BZOJ.1178.[APIO2009]会议中心(贪心 倍增)

    BZOJ 洛谷 \(Description\) 给定\(n\)个区间\([L_i,R_i]\),要选出尽量多的区间,并满足它们互不相交.求最多能选出多少个的区间以及字典序最小的方案. \(n\leq2 ...

  2. [APIO2009]会议中心(贪心)

    P3626 [APIO2009]会议中心 题目描述 Siruseri 政府建造了一座新的会议中心.许多公司对租借会议中心的会堂很 感兴趣,他们希望能够在里面举行会议. 对于一个客户而言,仅当在开会时能 ...

  3. [APIO2009]会议中心

    [APIO2009]会议中心 题目大意: 原网址与样例戳我! 给定n个区间,询问以下问题: 1.最多能够选择多少个不相交的区间? 2.在第一问的基础上,输出字典序最小的方案. 数据范围:\(n \le ...

  4. 【题解】[APIO2009]会议中心

    [题解][P3626 APIO2009]会议中心 真的是一道好题!!!刷新了我对倍增浅显的认识. 此题若没有第二份输出一个字典序的方案,就是一道\(sort+\)贪心,但是第二问使得我们要用另外的办法 ...

  5. BZOJ1178 [Apio2009]CONVENTION会议中心 贪心 set

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1178 题意概括 一堆线段,现在取出最多条数,使其互不覆盖,并输出字典序最小的方案. 题解 这题好坑 ...

  6. BZOJ1178或洛谷3626 [APIO2009]会议中心

    BZOJ原题链接 洛谷原题链接 第一个问题是经典的最多不相交区间问题,用贪心即可解决. 主要问题是第二个,求最小字典序的方案. 我们可以尝试从\(1\to n\)扫一遍所有区间,按顺序对每一个不会使答 ...

  7. bzoj1178/luogu3626 会议中心 (倍增+STL::set)

    贪心地,可以建出一棵树,每个区间对应一个点,它的父亲是它右边的.与它不相交的.右端点最小的区间. 为了方便,再加入一个[0,0]区间 于是就可以倍增来做出从某个区间开始,一直到某个右界,这之中最多能选 ...

  8. Luogu 3626 [APIO2009]会议中心

    很优美的解法. 推荐大佬博客 如果没有保证字典序最小这一个要求,这题就是一个水题了,但是要保证字典序最小,然后我就不会了…… 如果一条线段能放入一个区间$[l', r']$并且不影响最优答案,那么对于 ...

  9. P3626 [APIO2009]会议中心

    传送门 好迷的思路-- 首先,如果只有第一问就是个贪心,排个序就行了 对于第二问,我们考虑这样的一种构造方式,每一次都判断加入一个区间是否会使答案变差,如果不会的话就将他加入别问我正确性我不会证 我们 ...

随机推荐

  1. CSS盒模型的介绍

    CSS盒模型的概念与分类      CSS盒模型就是一个盒子,封装周围的HTML元素,它包括内容content.边框border.内边距padding.外边距margin. CSS盒模型分为标准模型和 ...

  2. css中那些属性可以被继承

    主要的有: 字体相关:line-height, font-family, font-size, font-style, font-variant, font-weight, font 文本相关: le ...

  3. hosts 文件

    各系统平台hosts文件存放路径 路径如下: Windows系统: C:\Windows\System32\drivers\etc\hosts        Linux系统:/etc/hosts    ...

  4. VUE 配置vue-devtools调试工具

    1. 通过 Git 克隆项目到本地 git clone https://github.com/vuejs/vue-devtools.git 2. Git 进入到 vue-devtools 所在目录,然 ...

  5. Stackoverflow 珠玑:C#封装重试指定次数的功能

    最近写的一个 .NET Core 爬虫里用到了需要多次重试的功能,本着无脑输出的精神,google 了一下,还真给我找到了: public static T Retry<T, TExceptio ...

  6. (网页)AngularJS中【Error: [$rootScope:inprog]】的解决办法(转)

    转自CSDN: Error: [$rootScope:inprog] http://errors.angularjs.org/1.5.8/$rootScope/inprog?p0=%24apply 如 ...

  7. JavaScript变量提升的理解

    变量提升 先说三句总结性的话: let 的「创建」过程被提升了,但是初始化没有提升. var 的「创建」和「初始化」都被提升了. function 的「创建」「初始化」和「赋值」都被提升了. 所以,我 ...

  8. Ubuntu18.04 更换源

    在虚拟机新建一个Ubuntu18.04.1-live-server-amd64当做服务器 在安装软件时报错: slave@slave:~$ sudo -s[sudo] password for sla ...

  9. Mysqli面向对象操作数据库

    Mysqli面向对象操作数据库 首先配置一下数据库: 接着用PHP中的Mysqli扩展库面向对象查询这个数据表. 操作分为以下几个步骤: 连接数据库 操作数据库 处理结果 关闭资源 <?php ...

  10. map的使用注意事项

    map是无序的,每次打印出来的map都会不一样,它不能通过index获取,而必须通过key获取 map的长度是不固定的,也就是和slice一样,也是一种引用类型 内置的len函数同样适用于map,返回 ...