单调序列 Proofs from THE BOOK chapter22

此书的22章讲到了鸽笼原理,其中一道题挺有意思

在任何一个大小为mn+1的序列,a1, a2,..., 每个实数各不相同。要么存在一个大小为m+1的递增序列,要么大小为n+1的递减序列,或者同时存在。 

下面是书中给出的解答:

先做个定义:对于某个ai,都有一个ti代表了以ai为起始点的最大上升序列的长度。

举个例子m=2,n=2的序列

1 2 -1 0 3

相应的ti序列就是

3 2 3 2 1

1)如果ti>=m+1,那么存在一个m+1的递增序列,问题得证明。

2)那么假定所有ti<=m。总共有mn+1个t,它的取值范围是{1,...,m}。根据鸽笼原理,那么有n+1个数具有相同t值。

假定这个值为s,且1<= s <= m。

考察这n+1个数{a(j,1),a(j,2),...,a(j, n+1)},我们可以得到这样的结论a(j,1) >a(j,2)>...>a(j,n+1)。

为什么呢?如果相邻的两个数a(j, i)<a(j, i+1)。以a(j, i+1)开头已经有长度为s的递增序列了,再加上a(j, i), 就会找到以a(i,j)为开头的递增序列长度为s+1。与原先的假设矛盾!

根据a(j,1) >a(j,2)>...>a(j,n+1),我们可以得到一个长度为n+1的递减序列。问题的证

说说我的解题思路:

对于每一个ai,定义以它为结尾的最大递增,递减序列长度分别为(xi, yi)

1)如果xi>=m+1,或则yi<=n+1,那么问题得证!

2)我们假定1<=xi<=m,且1<=yi<=n。

首先我们可以得到任意两对(xi, yi) (xj, yj)不完全同。如果完全相同,会存在矛盾

例如ai 的是(3, 5), aj的也是(3,5)。如果ai<aj,那么实际可以找到一个以aj为结尾的长度为4的单调递增序列。ai>aj也是同理。

由于xi, yi的取值范围,总共只有mn对完全不同的数。

例如m=2, n=3,只有(1,1 (1,2) (1,3) (2,1) (2,2) (2,3)

但是我们有mn+1对(xi, yi),必然存在两对数完全相同,与上述的推论“任意两对(xi, yi) (xj, yj)不完全同”矛盾。因为有mn个笼子和mn+1只鸽子。

因此命题的得证

时间: 2024-10-11 23:16:06

单调序列 Proofs from THE BOOK chapter22的相关文章

Old Sorting(转化成单调序列的最小次数,置换群思想)

Old Sorting Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice LightOJ 1166 Description Given an array containing a permutation of 1 to n, you have to find the minimum number of swaps to sort the array i

VJ - dp - Monkey and Banana - 最长单调序列

https://vjudge.net/contest/353156#problem/A 一开始想着按背包做 = = 我的dp还是太菜了 应该按照单调序列做 1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 struct node{ 6 int l; 7 int s; 8 int v; 9 int ans; 10 node(){ 11 ans

CF713C Sonya and Problem Wihtout a Legend &amp; hihocoder1942 单调序列

这两个题是一样的,不过数据范围不同. 思路1: 在CF713C中,首先考虑使生成序列单调不下降的情况如何求解.因为单调上升的情况可以通过预处理将a[i]减去i转化成单调不下降的情况. 首先,生成的序列中的每个数一定是原序列中的数.于是可以通过dp+离散化技巧解决.dp[i][j]表示把前i个数变成单调不下降的序列,并且a[i]不超过第j大的数所需要的最小代价. 实现1: 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef lo

单调序列例题

一, 给定一个区间,求所有区间长度为L的区间的最大值和最小值 二, 该题有很多做法. 自然用的是滑动窗口(单调队列) 可能的做法: O(nlogn)的线段树 O(nlogn)的带删除优先队列(对顶堆) 还能再快一点吗? O(n)-O(1)RMQ代替线段树 三, 单调队列和单调栈的意思一样,始终要你维持一个单调递增或者递减的属性. 比你小还比你强,我哭了. 1 const int N= 5000010 ; 2 int q[N],l=1,r=1,a[N] , mx , mn, inq[N],n,m;

拦截导弹;合唱队形;友好城市——基本的单调序列动态规划吧

合集,三个题目基本上都一样.耗时也不贴了. 拦截导弹: 1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int N=128; 5 int n=1,val[N]; 6 int up[N],dn[N],cnt1,cnt2; 7 int main(){ 8 for(int i=0;i<N;i++)up[i]=dn[i]=1; 9 while(cin>>val[n])n++;n-

nyist oj 214 单调递增子序列(二) (动态规划经典)

单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度. 如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5. 输入 有多组测试数据(<=7) 每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=1

最长单调子序列(O(n^2) 和 O(nlg(n))))

给出一个数n,然后给出n个数,求n个数的最长单调子序列.如: n = 7 7    1     5    2    9    3    6 方法一:DP dp[i] 表示元素值不超过i时的最长单调序列.时间复杂度为O(n^2)则可以这样: #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 100000 int a[N]; int dp[N]; int main() { //freop

最长不下降子序列 nlogn &amp;&amp; 输出序列

最长不下降子序列实现: 利用序列的单调性. 对于任意一个单调序列,如 1 2 3 4 5(是单增的),若这时向序列尾部增添一个数 x,我们只会在意 x 和 5 的大小,若 x>5,增添成功,反之则失败.由于普通代码是从头开始比较,而 x 和 1,2,3,4 的大小比较是没有用处的,这种操作只会造成时间的浪费,所以效率极低.对于单调序列,只需要记录每个序列的最后一个数,每增添一个数 x,直接比较 x 和末尾数的大小.只有最后一个数才是有用的,它表示该序列的最大限度值. 实现方法就是新开一个数组 d

830. 单调栈

给定一个长度为N的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出-1. 输入格式 第一行包含整数N,表示数列长度. 第二行包含N个整数,表示整数数列. 输出格式 共一行,包含N个整数,其中第i个数表示第i个数的左边第一个比它小的数,如果不存在则输出-1. 数据范围 1≤N≤1051≤N≤1051≤数列中元素≤1091≤数列中元素≤109 输入样例: 5 3 4 2 7 5 输出样例: -1 3 -1 2 2 思路:用栈维护一个单调序列 import java.util.Scanner