首页 > 代码库 > 51nod 1218 最长递增子序列 V2(dp + 思维)
51nod 1218 最长递增子序列 V2(dp + 思维)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1218
题解:先要确定这些点是不是属于最长递增序列然后再确定这些数在最长递增序列中出现的次数,如果大于1次显然是可能出现只出现1次肯定是必然出现。那么就是怎么判断是不是属于最长递增序列,这个只要顺着求一下最长递增标一下该点属于长度几然后再逆着求一下最长递减标一下该点属于长度几如果两个下标之和等于最长长度+1那么该点就属于最长递增序列,然后就是求1~len(len表示最长的长度)中各个长度出现的次数就行。
#include <iostream>#include <cstring>#include <cstdio>#include <vector>#define inf 0X3f3f3f3fusing namespace std;const int M = 5e4 + 10;int a[M] , b[M] , dpa[M] , dpb[M] , vis[M];bool vs[M];int binsearch(int l , int r , int num) { int mid = (l + r) >> 1; int ans = 0; while(l <= r) { mid = (l + r) >> 1; if(b[mid] > num) r = mid - 1; else { ans = mid; l = mid + 1; } } return ans;}int binsearch2(int l , int r , int num) { int mid = (l + r) >> 1; int ans = 0; while(l <= r) { mid = (l + r) >> 1; if(b[mid] < num) r = mid - 1; else { ans = mid; l = mid + 1; } } return ans;}int main() { int n; scanf("%d" , &n); for(int i = 1 ; i <= n ; i++) scanf("%d" , &a[i]); int len = 0; b[0] = -1; for(int i = 1 ; i <= n ; i++) { if(a[i] > b[len]) { len++; b[len] = a[i]; dpa[i] = len; continue; } else { int pos = binsearch(1 , len , a[i]); b[pos + 1] = min(b[pos + 1] , a[i]); dpa[i] = pos + 1; } } int len2 = 0; memset(b , inf , sizeof(b)); for(int i = n ; i >= 1 ; i--) { if(a[i] < b[len2]) { len2++; b[len2] = a[i]; dpb[i] = len2; } else { int pos = binsearch2(1 , len2 , a[i]); b[pos + 1] = max(b[pos + 1] , a[i]); dpb[i] = pos + 1; } } memset(vs , false , sizeof(vs)); for(int i = 1 ; i <= n ; i++) { if(dpa[i] + dpb[i] == len + 1) { vis[dpa[i]]++; vs[i] = true; } } printf("A:"); for(int i = 1 ; i <= n ; i++) { if(vis[dpa[i]] > 1 && vs[i]) printf("%d " , i); } printf("\n"); printf("B:"); for(int i = 1 ; i <= n ; i++) { if(vis[dpa[i]] == 1 && vs[i]) printf("%d " , i); } printf("\n"); return 0;}
51nod 1218 最长递增子序列 V2(dp + 思维)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。