2013 多校第一场 hdu 4604 Deque
2013-07-24 12:35
357 查看
hdu 4604
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4604
题目大意:给你一个序列和一个双端队列,维持队列里是不下降的,问你一个一个加序列里的元素,队列的最大的长度是多少。
思路:首先,只考虑一个单调上升的双端队列,那么对于序列 A 和 队列 Q,找出以 Ai 为首的最长上升子序列和最长下降子序列,那么 Q 能维持的最大长度为这两个长度之和。现在,题目中的元素是可以重复的,那么,先求出以 Ai 为首的最长不下降子序列和最长不上升子序列,那么 Q 能维持的最大长度 = 这两个的长度之和 - 这两个序列中 Ai 个数的最小值。
以上都是解题报告里说的,自己比赛做的时候,因为情况太多了,进来又出去的,选了某个,又影响后面的,脑子很乱,根本没想到这一点,但是的确脑子里有出现过求最长递增子序列,没有深究下去,也没有发现他这个双端队列两端能进出的本质吧。。同时,有了思路,这道题最关键的地方还是在于判重,要深入理解LIS O(nlogn)这个算法的过程,其实当当前处理元素为 Ai 时,找到它的 pos ,那么d[1]~d[ pos ] 这里面存的就是以它为结尾的最长序列,再分别二分求出这两个序列中 Ai 的个数就行了。
代码如下:
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4604
题目大意:给你一个序列和一个双端队列,维持队列里是不下降的,问你一个一个加序列里的元素,队列的最大的长度是多少。
思路:首先,只考虑一个单调上升的双端队列,那么对于序列 A 和 队列 Q,找出以 Ai 为首的最长上升子序列和最长下降子序列,那么 Q 能维持的最大长度为这两个长度之和。现在,题目中的元素是可以重复的,那么,先求出以 Ai 为首的最长不下降子序列和最长不上升子序列,那么 Q 能维持的最大长度 = 这两个的长度之和 - 这两个序列中 Ai 个数的最小值。
以上都是解题报告里说的,自己比赛做的时候,因为情况太多了,进来又出去的,选了某个,又影响后面的,脑子很乱,根本没想到这一点,但是的确脑子里有出现过求最长递增子序列,没有深究下去,也没有发现他这个双端队列两端能进出的本质吧。。同时,有了思路,这道题最关键的地方还是在于判重,要深入理解LIS O(nlogn)这个算法的过程,其实当当前处理元素为 Ai 时,找到它的 pos ,那么d[1]~d[ pos ] 这里面存的就是以它为结尾的最长序列,再分别二分求出这两个序列中 Ai 的个数就行了。
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF = 0x0fffffff ; const int MAXN = 100011 ; int n; int a[MAXN],d[2][MAXN]; int tot0,tot1; int ans; void lis() { d[0][1]=a ; tot0=1; d[1][1]=a ; tot1=1; for(int i=n-1;i>=1;i--) { int pos0; if(a[i]>=d[0][tot0]) { tot0++; d[0][tot0]=a[i]; pos0 = tot0; } else { pos0 = upper_bound(d[0]+1,d[0]+tot0+1,a[i])-d[0]; d[0][pos0] = a[i]; } int pos1; if(a[i]<=d[1][tot1]) { tot1++; d[1][tot1] = a[i]; pos1 = tot1; } else { int l = 1,r = tot1; while(l<r) { int m = l+r>>1; if(d[1][m]>=a[i]) { l=m+1; } else { r = m; } } pos1 = l; d[1][pos1] = a[i]; } int f0 = pos0-(lower_bound(d[0]+1,d[0]+pos0+1,a[i])-d[0])+1; int l = 1,r = pos1; while(l<r) { int m = l+r>>1; if(d[1][m]==a[i]) { r= m; } else if(d[1][m]>a[i]) l = m+1; else r = m-1; } int f1 = pos1 - l+1; //printf("pos0 = %d,pos1 = %d,f0 = %d,f1 = %d\n",pos0,pos1,f0,f1); ans = max(ans,pos0+pos1-min(f0,f1)); } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } ans=1; lis(); printf("%d\n",ans); } return 0; } /* 10 1 2 1 3 2 1 3 1 2 2 */
相关文章推荐
- hdu 4604 Deque 多校第一场
- poj 4604 Deque-----2013多校联合赛第一场--1005
- 2013 多校第一场 hdu 4602 Partition
- 2013 多校第一场 hdu 4609 3-idiots(FFT)
- 2013 多校第一场 hdu 4607 Park Visit
- 2013 多校第一场 hdu 4610 Cards
- hdu 4607 park visit 2013多校联合训练第一场
- 2013 多校第一场 hdu 4605 Magic Ball Game
- hdu 4602 partition 2013多校联合训练第一场
- HDU杭电2013 多校第一场解题报告
- 2013多校联合4 1010 K-string (hdu 4641)
- 2013 多校第五场 hdu 4651 Partition
- HDU 4655 Cut Pieces(2013多校6 1001题 简单数学题)
- HDU 4655 2013多校联合赛第6场 Cut Pieces
- 2013 多校第六场 hdu 4661 Message Passing(树形DP+拓展欧几里得)
- 2013杭电网络赛第一场 1005 Deque
- hdu 4869 Turn the pokers (2014多校联合第一场 I)
- hdu 4604 Deque
- HDU 4666 Hyperspace (2013多校7 1001题 最远曼哈顿距离)
- HDU 4611 Balls Rearrangement(2013多校2 1001题)