以下内容参考2019年集训队论文《浅谈杨氏矩阵在信息学竞赛中的应用》

1.前置知识

杨表

标准杨表:一张网格图,满足以下条件——

1.设其有$m$行、第$i$行有$a_{i}$个格子(格子左对齐),则$a_{1}\ge a_{2}\ge ...\ge a_{m}$

2.每一个格子内有一个正整数,且每行每列都严格单调递增

3.记$n=\sum_{i=1}^{m}a_{i}$(即格子总数),所有格子内的正整数恰构成1到$n$的排列

半标准杨表:一张网格图,满足以下条件——

1.设其有$m$行、第$i$行有$a_{i}$个格子(格子左对齐),则$a_{1}\ge a_{2}\ge ...\ge a_{m}$

2.每一个格子内有一个正整数,且每行单调不下降、每列严格单调递增

(以下杨表默认均指半标准杨表)

记$\empty$为空杨表(即$m=0$时),$S_{i,j}$为杨表$S$第$i$行第$j$列的元素

插入和删除

行插入:对于一个杨表$S$,将$x\in Z^{+}$行插入$S$,过程如下:

1.找到第$i$行中第一个大于等于$x$的元素,将其与$x$交换(初始$i=1$)

2.将$i$增加1并重复第一步,直至第$i$行中没有大于等于$x$的元素,则将$x$加入到该行末尾

并记最终得到的杨表为$S\leftarrow x$

列插入:与行插入类似,将过程中的"行"将改为"列"即可,并记最终得到的杨表为$x\rightarrow S$

删除:对于一个杨表$S$,将第$i$行最后一个元素删除,过程如下:

1.找到第$i-1$行中最后一个小于等于$x$的的元素,将其与$x$交换(初始$x=S_{i,a_{i}}$)

2.将$i$减小1并重复第一步,直至$i=1$则结束

并记最终得到的杨表为$S-i$(其中$1\le i\le m$)

性质

性质1.1:对杨表执(行/列)插入或删除操作后仍是杨表

性质1.2:行插入和删除操作互为逆运算

关于这一性质,更完整的描述即以下两点——

1.假设在杨表$S$中行插入$x$后最终位于第$i$行,则$S=(S\leftarrow x)-i$

2.假设在杨表$S$中删除第$i$行后结束时的元素为$x$,则$(S-i)\leftarrow x=S$

性质1.3:$(S\leftarrow x)^{T}=x\rightarrow S^{T}$(其中$S$为标准杨表,$S^{T}$即将其转置)

性质1.4:$(x\rightarrow S)\leftarrow y=x\rightarrow(S\leftarrow y)$

关于这一性质的证明,参考论文的参考文献[10]

2.杨表和排列

对于一个排列$\{p_{i}\}$,构造其对应的杨表$S_{p}=((\empty\leftarrow p_{1})\leftarrow p_{2})\leftarrow...\leftarrow p_{n}$

在构造$S_{p}$的过程中,若插入$p_{x}$后$p_{x}$位于第$i$行第$j$列,则令$Q_{p}$第$i$行第$j$列的元素为$x$

性质2.1:$S_{p}$和$Q_{p}$均为标准杨表且两者形状相同(形状即每行元素个数相同)

性质2.2:$S_{\{p_{n},p_{n-1},...,p_{1}\}}=S_{p}^{T}$

关于这一性质的证明,根据性质1.3和1.4并归纳即可

性质2.3:对于任意两个形状相同的标准杨表$S_{1}$和$S_{2}$,恰存在一个排列$p_{i}$使得$(S_{1},S_{2})=(S_{p},Q_{p})$

关于这一性质的证明,根据性质1.2即可通过$(S_{1},S_{2})$构造排列$p_{i}$

性质2.4:$p_{i}$最长${\rm LIS}_{k}$子序列长度为$S_{p}$的前$k$列长度和

(其中${\rm LIS}_{k}$序列即最长上升子序列长度小于等于$k$的序列)

关于这一性质的证明,参考论文5.1的部分

3.杨表计数

定义序列$\{a_{1},a_{2},...,a_{m}\}\vdash n$当且仅当$a_{1}\ge a_{2}\ge ...\ge a_{m}$且$\sum_{i=1}^{m}a_{i}=n$

记$f_{\{a_{1},a_{2},...,a_{m}\}}$为第$i$行有$a_{i}$个格子的标准杨表个数,显然要有$a_{1}\ge a_{2}\ge ...\ge a_{m}$

性质3.1:$\sum_{a\vdash n}f_{a}^{2}=n!$

性质3.2:$f_{a}=\frac{n!}{\prod_{1\le i\le m,1\le j\le a_{i}}h_{a}(i,j)}$(其中$h_{a}(i,j)$表示$(i,j)$正右和正下方的格子数+1)

关于这一性质的证明,参考论文6.1的部分

类似地,记$g_{n,\{a_{1},a_{2},...,a_{m}\}}$为第$i$行有$a_{i}$个格子且值域为$[1,n]$的半标准杨表数

性质3.3:$g_{n,a}=\prod_{1\le i\le m,1\le j\le a_{i}}\frac{n+j-i}{h_{a}(i,j)}$

关于这一性质的证明,参考论文8.1和8.2的部分

4.其他

论文中还有以下几部分的内容:

(1)杨表和矩阵(第4部分)

(2)杨表和路径计数(6.2的部分和第7部分)

(3)复杂的杨表计数(第9部分)

(补充一下$q$的范围:$q\le 2\times 10^{5}$)

关于本题,将询问离线后按照$m$从小到大排序,并将所有数依次行插入杨表

暴力插入的复杂度为$o(n\log n)$,显然无法通过

对于杨表$S$,仅维护$S$的前$\sqrt{n}$行和$S^{T}$的前$\sqrt{n}$行(也即$S$的前$\sqrt{n}$列),注意到$S$中每一个格子的左上角格子必然是全的,因此这包含了$S$的所有元素(否则元素个数$>n$)

前者单次插入复杂度即$o(\sqrt{n}\log n)$,但后者仍难以处理

构造$S'$也为所有数依次行插入杨表的结果,但将比较中的"大于等于"改为"小于",那么$S'$前$k$行的长度和即为最长${\rm LIS}_{k}$子序列,注意到这与$S^{T}$相同

换言之,有$S'$和$S^{T}$形状相同,同时我们仅关心于形状而不关心于具体的数,即可以维护$S'$代替$S^{T}$,同样单次插入复杂度为$o(\sqrt{n}\log n)$

关于查询,根据性质2.4即求前$k$列的长度和,注意到每次插入对杨表的形状只有一处变化,因此用树状数组维护即可,修改和询问复杂度均为$o(\log n)$

总复杂度为$o(n\sqrt{n}\log n+q\log n)$,可以通过

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 50005
4 #define K 250
5 struct Data{
6 int l,k,id;
7 bool operator < (const Data &a)const{
8 return l<a.l;
9 }
10 }q[N<<2];
11 vector<int>v0[K],v1[K];
12 int n,m,k,a[N],f[N],ans[N<<2];
13 int lowbit(int k){
14 return (k&(-k));
15 }
16 void update(int k){
17 while (k<=n){
18 f[k]++;
19 k+=lowbit(k);
20 }
21 }
22 int query(int k){
23 int ans=0;
24 while (k){
25 ans+=f[k];
26 k-=lowbit(k);
27 }
28 return ans;
29 }
30 void add0(int x){
31 for(int i=1;i<=k;i++){
32 if ((!v0[i].size())||(v0[i].back()<x)){
33 v0[i].push_back(x);
34 if (v0[i].size()>k)update(v0[i].size());
35 return;
36 }
37 swap(*lower_bound(v0[i].begin(),v0[i].end(),x),x);
38 }
39 }
40 void add1(int x){
41 for(int i=1;i<=k;i++){
42 if ((!v1[i].size())||(v1[i].back()<=x)){
43 v1[i].push_back(x);
44 update(i);
45 return;
46 }
47 swap(*upper_bound(v1[i].begin(),v1[i].end(),x),x);
48 }
49 }
50 int main(){
51 scanf("%d%d",&n,&m);
52 k=(int)sqrt(n);
53 for(int i=1;i<=n;i++)scanf("%d",&a[i]);
54 for(int i=1;i<=m;i++){
55 scanf("%d%d",&q[i].l,&q[i].k);
56 q[i].id=i;
57 }
58 sort(q+1,q+m+1);
59 for(int i=1,j=1;i<=n;i++){
60 add0(a[i]),add1(-a[i]);
61 while ((j<=m)&&(q[j].l==i)){
62 ans[q[j].id]=query(q[j].k);
63 j++;
64 }
65 }
66 for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
67 }

[loj2265]最长上升子序列的更多相关文章

  1. 用python实现最长公共子序列算法(找到所有最长公共子串)

    软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...

  2. 动态规划之最长公共子序列(LCS)

    转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...

  3. [Data Structure] LCSs——最长公共子序列和最长公共子串

    1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...

  4. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  5. LintCode 77: 最长公共子序列

    public class Solution { /** * @param A, B: Two string. * @return: the length of the longest common s ...

  6. 最长下降子序列O(n^2)及O(n*log(n))解法

    求最长下降子序列和LIS基本思路是完全一样的,都是很经典的DP题目. 问题大都类似于 有一个序列 a1,a2,a3...ak..an,求其最长下降子序列(或者求其最长不下降子序列)的长度. 以最长下降 ...

  7. 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题

    先要搞明白:最长公共子串和最长公共子序列的区别.    最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...

  8. [BZOJ3173][Tjoi2013]最长上升子序列

    [BZOJ3173][Tjoi2013]最长上升子序列 试题描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上 ...

  9. 3173: [Tjoi2013]最长上升子序列

    原题:http://www.lydsy.com/JudgeOnline/problem.php?id=3173 题解:促使我写这题的动力是,为什么百度遍地是Treap,黑人问号??? 这题可以用线段树 ...

随机推荐

  1. 面试官问我MySQL调优,我真的是

    面试官:要不你来讲讲你们对MySQL是怎么调优的? 候选者:哇,这命题很大阿...我认为,对于开发者而言,对MySQL的调优重点一般是在「开发规范」.「数据库索引」又或者说解决线上慢查询上. 候选者: ...

  2. 高中最后一刻&大学第一课&为人师的责任

    文章不是技术文,只是分享一些感想,作为一只程序猿,不说好好敲代码,跑出来思考人生,不是合格的程序猿,罪过罪过,自我反思3秒钟,我们继续,毕竟程序猿的人生不只是Coding,也希望自己这点感想被更多刚入 ...

  3. Java(12)方法的重载

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201592.html 博客主页:https://www.cnblogs.com/testero ...

  4. wget命令8种实用用法

    大家好,我是良许. wget 是一个可以从网络上下载文件的免费实用程序,它的工作原理是从 Internet 上获取数据,并将其保存到本地文件中或显示在你的终端上. 这实际上也是大家所使用的浏览器所做的 ...

  5. 测试小姐姐问我 gRPC 怎么用,我直接把这篇文章甩给了她

    原文链接: 测试小姐姐问我 gRPC 怎么用,我直接把这篇文章甩给了她 上篇文章 gRPC,爆赞 直接爆了,内容主要包括:简单的 gRPC 服务,流处理模式,验证器,Token 认证和证书认证. 在多 ...

  6. [Beta]the Agiles Scrum Meeting 9

    会议时间:2020.5.24 21:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 issue yjy 撰写技术博客 tq 实现评测机获取评测状态功能 评测部分增加更多评测指标 wjx ...

  7. 【二食堂】Beta - Scrum Meeting 2

    Scrum Meeting 2 例会时间:5.14 18:30~18:50 进度情况 组员 当前进度 今日任务 李健 1. 还在进行摸索,目前做出了一个demo可以进行简单的划词 issue 1. 继 ...

  8. CSDN app分析

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) (北京航空航天大学 - 计算机学院) 这个作业的要求在哪里 个人博客作业-软件案例分析 我的教学班级 005 说说csd ...

  9. 万能构造解决Rolle中值问题

    只要原函数是两个函数的乘积形式,皆可此构造.

  10. Java:检查异常与未检查异常

    一.异常的介绍 Throwable 是 Java 中所有错误和异常的超类.Java 虚拟机仅抛出属于此类(或其子类之一)的实例对象,或者是 throw 语句也可以抛出该对象.同样,catch 子句中的 ...