https://vjudge.net/problem/TopCoder-13460

简要题意:给出 \(n\) 段从 \(1\) 到 \(n\) 编号的等长区间,保证区间的端点互不相同。区间可以选取其左端点或右端点值作为键值。求将区间按键值从小到大进行排序之后可能出现多少种不同的编号序列。对 \(10^9+7\) 取模。(\(n\le 5\times 10^5\))。

首先要知道序列不同当且仅当存在两编号在序列中的相对位置不同。

将区间按左端点升序排序,则其右端点也形成升序。尝试按排序后顺序进行增量,为求出答案自然想到记 \(f_i\) 为前 \(i\) 个区间任选键值排序能得到的序列的种数。

现在 \(f_i\) 不好求出,可以尝试枚举第 \(i\) 个区间选取了哪个键值。如果选取较大的键值,那么此时能得到的序列种数即为 \(f_{i-1}\),否则可以考虑再记 \(g_i\) 为第 \(i\) 个区间选取了左键值,前 \(i-1\) 个区间任选键值排序后能得到的序列的种数。

那么自然 \(f_i=f_{i-1}+g_{i}-\)(\(i\) 选左右键值时均能得到的序列的种数)。分析括号内要求的序列的性质,可以发现这样的序列必须能在 \(i\) 选左键值且排在最后一位的情况下被构造出,并且这也是充分条件。也就是说我们要求在 \(i\) 选左键值且排在最后一位的情况下能被构造出的序列的个数。

这就相当于求所有右端点在范围 \((l_i,r_i]\) 内的区间都选取左端点的情况下能够形成多少种序列。记该范围内右端点最靠左的区间为 \(j\),那么该问题相当于在 \(g_j\) 上插入了若干个端点,而每个端点都可能将 \(g_j\) 原有的某种序列分裂成若干种不同序列。

但我们运气较好,\(g_j\) 的所有序列都满足排在 \(j\) 后的区间选择了它的右端点从而位置固定,所以在 \(g_j\) 后插入的新端点同样位置固定,并不会导致原有序列的分裂,因而该问题的答案就是 \(g_j\),由此终于得到 \(f_i=f_{i-1}+g_i-g_j\)。

乘胜追击,我们继续思考 \(g_i\) 如何求得。继续尝试枚举区间 \(i-1\) 的选择。这里由于 \(i\) 选择了左端点,所以所有右端点在范围 \((l_i,r_i]\) 内的区间选取左右端点能得到的序列一定不同,所以枚举后只要进行简单加和。

如果区间 \(i-1\) 选择了左端点,那么与先前的分析相同,我们得到序列种数为 \(g_{i-1}\)。否则我们继续枚举区间 \(i-2\),直到因编号在 \([j,i)\) 的区间均选取右端点而导致要讨论区间 \(j-1\)。不过这时我们可以发现无需枚举,种数就是 \(f_{j-1}\)。

由此我们得到 \(g_i=f_{j-1}+\sum_{k=j}^{i-1}g_k\)。再结合 \(f_i=f_{i-1}+g_i-g_j\),在 \(i\) 的增量过程中维护数值单调不降的 \(j\),并在 \(i\) 与 \(j\) 的移动过程中顺便维护 \(\sum_{k=j}^{i-1}g_k\),就能 \(O(n)\) 求出 \(f\) 和 \(g\),而答案即为 \(f_n\)。

总时间复杂度 \(O(n+\text{Sort}(n))\),\(\text{Sort}(n)\) 为将 \(n\) 个数进行排序的复杂度。

[TopCoder2014Final]FrozenStandings 解法探究的更多相关文章

  1. 对背包问题(Knapsack Problem)的算法探究

    对背包问题(Knapsack Problem)的算法探究 至繁归于至简,这次自己仍然用尽可能易理解和阅读的解决方式. 1.问题说明: 假设有一个背包的负重最多可达8公斤,而希望在背包中装入负重范围内可 ...

  2. 探究"补阶乘大法的本质"——糖水不等式!

    废话不多说先来康一条例题: 证明: 下面给出题目的一种解法(我称之为"补阶乘大法"): 思考:为什么补上一个阶乘(准确说不是阶乘,是两个数阶乘的之商)项,放缩后再给去掉,就能达到我 ...

  3. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  4. alias导致virtualenv异常的分析和解法

    title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...

  5. [原] KVM 虚拟化原理探究(1)— overview

    KVM 虚拟化原理探究- overview 标签(空格分隔): KVM 写在前面的话 本文不介绍kvm和qemu的基本安装操作,希望读者具有一定的KVM实践经验.同时希望借此系列博客,能够对KVM底层 ...

  6. Matlab数值计算示例: 牛顿插值法、LU分解法、拉格朗日插值法、牛顿插值法

    本文源于一次课题作业,部分自己写的,部分借用了网上的demo 牛顿迭代法(1) x=1:0.01:2; y=x.^3-x.^2+sin(x)-1; plot(x,y,'linewidth',2);gr ...

  7. [原] KVM 虚拟化原理探究 —— 目录

    KVM 虚拟化原理探究 -- 目录 标签(空格分隔): KVM KVM 虚拟化原理探究(1)- overview KVM 虚拟化原理探究(2)- QEMU启动过程 KVM 虚拟化原理探究(3)- CP ...

  8. [原] KVM 虚拟化原理探究(6)— 块设备IO虚拟化

    KVM 虚拟化原理探究(6)- 块设备IO虚拟化 标签(空格分隔): KVM [toc] 块设备IO虚拟化简介 上一篇文章讲到了网络IO虚拟化,作为另外一个重要的虚拟化资源,块设备IO的虚拟化也是同样 ...

  9. [原] KVM 虚拟化原理探究(5)— 网络IO虚拟化

    KVM 虚拟化原理探究(5)- 网络IO虚拟化 标签(空格分隔): KVM IO 虚拟化简介 前面的文章介绍了KVM的启动过程,CPU虚拟化,内存虚拟化原理.作为一个完整的风诺依曼计算机系统,必然有输 ...

随机推荐

  1. 四、Implementation: The Building Blocks 实现:构件

    四.Implementation: The Building Blocks 实现:构件 This is the essential part of this guide. We will introd ...

  2. 036—环境变量path

    day04 课堂笔记 1.开发第一个java程序:HelloWorld 1.1.程序写完以后,一定要ctrl+s进行保存 源代码若修改,需重新进行编译 1.2.编译阶段 怎么编译?使用什么命令?这个命 ...

  3. BUAA-软件工程第一次作业

    软件工程第一次作业 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 第1次个人作业 我在这个课程的目标 团队完成好的软件,并对自己作出规划 这个作 ...

  4. 使用json-path解析json

    在我们的日常开发中,有时候需要从一个json字符串中获取一个值,或者从一段json字符串中获取到某些值,如果先使用Gson或Jackson转换成java对象在获取值,有些时候是很麻烦的,那么有没有一种 ...

  5. Kruskal重构树-进阶

    例题一:区间最小生成树(NKOJ P8439) 简要题意: 一个n个点m条边的无向图,点编号1到n,边编号1到m.边有边权. 有q次操作,操作分两种: 1.k x y z:修改第k条边,使其连接的两点 ...

  6. CSP-S 2021 遗言

    感谢€€£,谢谢宁嘞! 第一题,€€£给了很多限制条件,什么"先到先得"."只有一个跑道",让它看起来很好做,然后来骗,来偷袭,广大"消费者" ...

  7. geos编译问题

    gdal编译geos的时候会用到geos_c_i.lib这个文件,我用cmake编译的时候仅仅产生geos_c.lib这个文件,所以只能使用nmake的编译方式来编译geos库,nmake编译geos ...

  8. 数组中重复的数字 牛客网 剑指Offer

    数组中重复的数字 牛客网 剑指Offer 题目描述 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中 ...

  9. PWN学习之整数溢出

    目录 PWN学习之整数溢出 整数溢出 溢出和回绕 漏洞多发函数 整数溢出例子 PWN学习之整数溢出 整数溢出 如果一个整数用来计算一些敏感数值,如缓冲区大小或数值索引,就会产生潜在的危险.通常情况下, ...

  10. Oracle 整库备份还原

    http://www.mamicode.com/info-detail-2481866.html sql语句 system用户登陆 查看表空间和存放位置 select t1.name,t2.name ...