[TopCoder2014Final]FrozenStandings 解法探究
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 解法探究的更多相关文章
- 对背包问题(Knapsack Problem)的算法探究
对背包问题(Knapsack Problem)的算法探究 至繁归于至简,这次自己仍然用尽可能易理解和阅读的解决方式. 1.问题说明: 假设有一个背包的负重最多可达8公斤,而希望在背包中装入负重范围内可 ...
- 探究"补阶乘大法的本质"——糖水不等式!
废话不多说先来康一条例题: 证明: 下面给出题目的一种解法(我称之为"补阶乘大法"): 思考:为什么补上一个阶乘(准确说不是阶乘,是两个数阶乘的之商)项,放缩后再给去掉,就能达到我 ...
- 探究javascript对象和数组的异同,及函数变量缓存技巧
javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...
- alias导致virtualenv异常的分析和解法
title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...
- [原] KVM 虚拟化原理探究(1)— overview
KVM 虚拟化原理探究- overview 标签(空格分隔): KVM 写在前面的话 本文不介绍kvm和qemu的基本安装操作,希望读者具有一定的KVM实践经验.同时希望借此系列博客,能够对KVM底层 ...
- Matlab数值计算示例: 牛顿插值法、LU分解法、拉格朗日插值法、牛顿插值法
本文源于一次课题作业,部分自己写的,部分借用了网上的demo 牛顿迭代法(1) x=1:0.01:2; y=x.^3-x.^2+sin(x)-1; plot(x,y,'linewidth',2);gr ...
- [原] KVM 虚拟化原理探究 —— 目录
KVM 虚拟化原理探究 -- 目录 标签(空格分隔): KVM KVM 虚拟化原理探究(1)- overview KVM 虚拟化原理探究(2)- QEMU启动过程 KVM 虚拟化原理探究(3)- CP ...
- [原] KVM 虚拟化原理探究(6)— 块设备IO虚拟化
KVM 虚拟化原理探究(6)- 块设备IO虚拟化 标签(空格分隔): KVM [toc] 块设备IO虚拟化简介 上一篇文章讲到了网络IO虚拟化,作为另外一个重要的虚拟化资源,块设备IO的虚拟化也是同样 ...
- [原] KVM 虚拟化原理探究(5)— 网络IO虚拟化
KVM 虚拟化原理探究(5)- 网络IO虚拟化 标签(空格分隔): KVM IO 虚拟化简介 前面的文章介绍了KVM的启动过程,CPU虚拟化,内存虚拟化原理.作为一个完整的风诺依曼计算机系统,必然有输 ...
随机推荐
- [调试笔记] 10.8模拟赛11 T4 甜圈
这题正解线段树维护哈希,同机房神犇已经讲的很明白了.这里只说sbwzx在调试的时候犯的sb错误. 1.关于pushdown和update 众所周知,sbwzx一写带lazy的线段树,就必在pushdo ...
- 上拉电阻大小对i2c总线的影响
漏极开路上拉电阻取值为何不能很大或很小? 如果上拉电阻值过小,Vcc灌入端口的电流(Ic)将较大,这样会导致MOS管V2(三极管)不完全导通(Ib*β<Ic),有饱和状态变成放大状态,这样端口输 ...
- 计算机网络之应用层概述(C/S模型与p2p模型)
文章转自:https://blog.csdn.net/weixin_43914604/article/details/105582318 学习课程:<2019王道考研计算机网络> 学习目的 ...
- 攻防世界 web1.view_source
右键不管用,F12打开控制台,直接查看flag.
- TCP之拥塞窗口原理
学过网络相关课程的,都知道TCP中,有两个窗口: 滑动窗口(在我们的上一篇文章中有讲),接收方通过通告发送方自己的可以接受缓冲区大小(这个字段越大说明网络吞吐量越高),从而控制发送方的发送速度. 拥塞 ...
- 查找最小生成树:普里姆算法算法(Prim)算法
一.算法介绍 普里姆算法(Prim's algorithm),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之 ...
- std::string类详解
之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必 担心内存是否足够.字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下(甚至 ...
- 01_WPF概述
目录 Windows 图形演化 高级API 分辨率无关性 WPF体系结构 我的微信公众号 Windows 图形演化 在 WPF 之前,windows 开发一直使用本质上相同的显示技术.每个传统 win ...
- sed 修改替换包含关键字的整行
查找关键字 user10 所在的行,替换整行内容为aaaaaaaaaa #sed -i "s/^.*user10.*$/aaaaaaaaaa/" useradd.txt
- Java测试开发--JSONPath、JSONArray、JSONObject使用(十)
一.Maven项目,pom.xml文件中导入 <dependency> <groupId>com.alibaba</groupId> <artifactId& ...