传送门


只有第一问就比较水了

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

考虑第二问。按照编号从小到大考虑每一条线段是否能够被加入。假设当前选了一个区间集合\(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. TUM数据集rgbd_benchmark工具的使用方法

    # 在学习视觉slam过程中,需要对数据集合进行预处理和对slam或者跟踪结果进行评价,TUM提供一组这样的工具,为了自己以后方便查找,于是把它记录下来 一.RGBD_Benchmark工具下载链接: ...

  2. ArcGIS Server Rest 认证过程分析

    1. http://192.168.1.220:6080/arcgis/admin/login?redirect= Request URL: http://192.168.1.220:6080/arc ...

  3. Django 拾遗

    1.python_2_unicode_compatible装饰器 from django.db import models from django.utils.encoding import pyth ...

  4. 手把手教你撸一个简易的 webpack

    背景 随着前端复杂度的不断提升,诞生出很多打包工具,比如最先的grunt,gulp.到后来的webpack和Parcel.但是目前很多脚手架工具,比如vue-cli已经帮我们集成了一些构建工具的使用. ...

  5. [20170617]vim中调用sqlplus.txt

    [20170617]vim中调用sqlplus.txt --//以前写过一篇emacs下调用sqlplus的文章,一直想学emacs,受限制自己掌握vim,对学习它没有兴趣,原链接如下:--//htt ...

  6. python自动化报告的输出

    1.设计简单的用例 2.设计用例 以TestBaiduLinks.py命名 # coding:utf-8 from selenium import webdriver import unittest ...

  7. 说说Android6.0动态申请权限的那些坑

    白天在做SDK23版本的适配,遇到了不少坑,现在抽空记下来,以此为戒. 首先要知道哪些坑,就得先了解一些定义和基本使用方式. 那么先介绍一下动态申请的权限分组情况. 下面的权限组是由谷歌官方定义的,目 ...

  8. Fragment分解使用

    Fragment碎片:作为Activity的一部分,不能单独使用: 1. Fragment特点: (1)一个Fragment可以在多个Activity中重用: (2)一个Activity内部可以嵌入多 ...

  9. layui框架学习记录

    自定义layui动态渲染的数据表格单元格样式 layui.use('table', function() { var table = layui.table; table.render({ elem: ...

  10. 社交网络编程API之iOS系统自带分享

    社交网络编程API 社交网络编程主要使用iOS提供的Social框架,目前Social框架主要包含两个类: SLComposeViewController 提供撰写社交信息(如微博信息)的视图控制器, ...