CSU 1807: 最长上升子序列~
来源:互联网 发布:md5码算法 编辑:程序博客网 时间:2024/05/29 15:43
Description
Bobo 在 ICPCCamp 学会了解决最长上升子序列问题后得到了一个长度为 n 的数列 p1,p2,…,pn.Bobo 想用 1,2,…,n 来替换其中值为 0 的元素,使得 p1,p2,…,pn 互不相同(即 p1,p2,…,pn 是 {1,2,…,n} 的排列)。现在 Bobo 想知道,替换后最长上升子序列的长度恰好为 (n-1) 数列的数量。Input
输入包含不超过 300 组数据,其中不超过 20 组的 n 超过 100.每组数据的第一行包含一个整数 n (1≤n≤105).第二行包含 n 个整数p1,p2,…,pn (0≤pi≤n).保证p1,p2,…,pn中非 0 的元素互不相同。Output
对于每组数据,输出一个整数表示要求的值。Sample Input
30 0 040 0 0 051 0 0 4 5
Sample Output
491
HINT
Source
湖南省第十二届大学生计算机程序设计竞赛
Bobo 在 ICPCCamp 学会了解决最长上升子序列问题后得到了一个长度为 n 的数列 p1,p2,…,pn.
Bobo 想用 1,2,…,n 来替换其中值为 0 的元素,使得 p1,p2,…,pn 互不相同(即 p1,p2,…,pn 是 {1,2,…,n} 的排列)。
现在 Bobo 想知道,替换后最长上升子序列的长度恰好为 (n-1) 数列的数量。
输入包含不超过 300 组数据,其中不超过 20 组的 n 超过 100.
每组数据的第一行包含一个整数 n (1≤n≤105).
第二行包含 n 个整数p1,p2,…,pn (0≤pi≤n).
保证p1,p2,…,pn中非 0 的元素互不相同。
湖南省第十二届大学生计算机程序设计竞赛
思路:很显然,要形成最长长度为n-1的上升序列,就是要将原来的自然序列中的某一个数,插入到相对于原来位置的其他位置中去,可以再最前面和最后面,这样就能保证最长上升子序列长度为n-1,,对于输入的a数组分情况讨论,a[i] = 0不影响,分的情况不讨论a[i] = 0的情况
对于自然序列1 2 3 4 .... i i+1.... i+j......n
形成n-1的长度可以转换为
1 2 3 ..... i+j i i+1 ... i+j-1....n
或者1 2 3 ......i+1 i+2......i+j i......n
其中有一段子段左移一位或者右移一位
(1)对于所有 a[i] == i
这种情况只需要对连续的0作为一个子串进行变换,很容易得出结果
(2)a[i] != i && abs(a[i] - i) > 1
由于是将某一个数插入到某个位置,那么如果存在abs(a[i] - i) > 1那么一定是由某个数的插入的到这个位置而不是某个子段移动得到
(3) 只剩下a[i] != i&& abs(a[i] - i) = 1的情况
这种情况有可能是长度为1的子段固定移动而来,对这种情况进行特殊判断
剩下的只可能某个连续的子段移动而来,计算这个结果即可
#include<cstdio>#include<cstring>#include<cmath>#include<map>#include<string>#include<stack>#include<vector>#include<queue>#include<set>#include<algorithm>#include<iostream>const int maxn = 1e5 + 10;typedef long long ll;using namespace std;ll a[maxn], b[maxn], n;int main(){ while(scanf("%lld", &n) != EOF) { ll s1 = 0, s2 = 0, ind = -1; ll f = 1; for(ll i = 1; i <= n; i++) { scanf("%lld", &a[i]); b[i] = a[i]; if(!a[i] || a[i] - i == 0) continue; ll c = a[i] - i; f = 0; if(ind < 0) ind = i; if(abs(c) > 1) ind = i; } if(!f) { if(abs(a[ind] - ind) > 1) { ll sign = 1, ty = a[ind]; //恢复自然序列 if(a[ind] < ind) { for(ll i = ind; i > a[ind]; i--) b[i] = b[i - 1]; b[ty] = ty; } else { for(ll i = ind; i < a[ind]; i++) b[i] = b[i + 1]; b[ty] = ty; } for(ll i = 1; i <= n; i++) { if(!b[i]) continue; if(b[i] != i) sign = 0; } printf("%lld\n", sign); } else { //固定交换而来 if(ind < n && a[ind + 1] && (a[ind] - ind) * (a[ind + 1] - ind - 1) == -1) { ll sign = 1; swap(b[ind], b[ind + 1]); for(ll i = 1; i <= n; i++) { if(!b[i]) continue; if(b[i] != i) sign = 0; } printf("%lld\n", sign); } else { ll sign = 1, sum = 0; ll id1 = ind, id2 = ind; //两个边界 for( ; id1 >= 1 && a[id1] != id1; id1--); for( ; id2 <= n && a[id2] != id2; id2++); for(ll i = id1 - 1; i >= 1; i--) { if(!a[i]) continue; if(a[i] != i) sign = 0; } for(ll i = id2 + 1; i <= n; i++) { if(!a[i]) continue; if(a[i] != i) sign = 0; } if(sign) { ll idx = ind; //ind ~ idx整体移动的序列的长度 for(ll i = ind; i <= n; i++) if(a[i] - i == a[ind] - ind) idx = i; if(a[ind] < ind) { sum = (id2 - idx) * (ind - id1 - 1); } else { sum = (ind - id1) * (id2 - idx - 1); } } printf("%lld\n", sum); } } } else { ll d = 1, sum = 0; while(d < n) { if(a[d]) { d++; continue; } ll i = d; for( ; i <= n && !a[i]; i++); i--; sum += (i - d) * (i - d); d = i + 1; } printf("%lld\n", sum); } } return 0;}
0 0
- CSU 1807: 最长上升子序列~
- CSU 1807 最长上升子序列~
- CSU 1120 病毒 最长公共上升子序列(LCIS)
- CSU 1047 最长上升子序列 (二分水过)
- 【模拟】CSU 1807 最长上升子序列~ (2016湖南省第十二届大学生计算机程序设计竞赛)
- 湖南省第12届大学生计算机程序设计大赛 最长上升子序列 csu 1807
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 从机器学习谈起
- 实现Socket通信
- Codeforces Round #360 A 简单模拟
- Win10下安装Win7(新买固态硬盘)
- 【省选模拟试题】计算器谜题
- CSU 1807: 最长上升子序列~
- 第二周项目2-程序的多文件组织
- 使用jsp实现网站计数的功能
- 进程间通信--管道
- UVA 1664 Conquer a New Region (并查集+贪心)
- AJAX
- HH实习
- 直播利器---AnyRTC实时视频连麦互动直播
- myeclipse 设置【新建类】快捷键