2017 ACM/ICPC Asia Regional Shenyang Online 1004 array array array 最长上升子序列(板子可以更新啦,复杂度nlog2(n))

来源:互联网 发布:小米mix网络类型选择 编辑:程序博客网 时间:2024/05/29 12:12

题目链接:array array array
题意:从给定n个元素的数组中删除k个元素,如果剩下的数组元素是一个非递增序列或者是一个非递减序列,则输出“A is a magic array.”,否则,输出“A is not a magic array.”
思路:等于求至少得删除几个元素使得原序列要么是个递增序列,要么是个递减序列,它等于 (n - max(最长递增子序列长度,最长递减子序列长度)),最后再和k比较就行了。
本题主要是复杂度n*n求最长上升子序列会被卡,n*log(n)才能过。

#include <iostream>#include <cstdio>#include <fstream>#include <algorithm>#include <cmath>#include <deque>#include <vector>#include <queue>#include <string>#include <cstring>#include <map>#include <stack>#include <set>#define Max(a,b) a>b?a:b#define Min(a,b) a>b?b:a#define mem(a,b) memset(a,b,sizeof(a))using namespace std;typedef long long ll;int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};const double eps = 1e-6;const double Pi = acos(-1.0);const int INF=0x3f3f3f3f;const int maxn = 1e5+10;int a[maxn];int dp1[maxn];int dp2[maxn];int tmp1,tmp2;int n;int find1(int tag,int rr,int* dp1){    int l = 1, r = rr,mid;    while(l <= r){        mid = (l + r)/2;        if(dp1[mid] == tag){            l = mid;            break;        }else if(dp1[mid] < tag){            l = mid + 1;        }else{            r = mid - 1;        }    }    return l;}int find2(int tag,int rr,int *dp2){    int l = 1, r = rr, mid;    while(l <= r){        mid = (r + l)/2;        if(dp2[mid] == tag){            l = mid;            break;        }else if(dp2[mid] < tag){            r = mid - 1;        }else{            l = mid + 1;        }    }    return l;}void LIS(){    tmp1 = 0,tmp2 = 0;    memset(dp1,INF,sizeof(dp1));    memset(dp2,0,sizeof(dp2));    dp1[0] = 0,dp2[0] = INF;    for(int i = 1; i <= n; i++){        int p = find1(a[i],tmp1,dp1);        if(p > tmp1) tmp1++;        dp1[p] = min(dp1[p],a[i]);//以上为求最长递增子序列        p = find2(a[i],tmp2,dp2);        if(p > tmp2) tmp2++;        dp2[p] = max(dp2[p],a[i]);//以上为求最长递减子序列    }}int main(){    int T,k;    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&k);        for(int i = 1 ; i <= n; i++)        {            scanf("%d",&a[i]);        }        LIS();        if(min(n - tmp1,n - tmp2) <= k){            printf("A is a magic array.\n");        }else{            printf("A is not a magic array.\n");        }    }    return 0;}

必须多做点DP题才行…

阅读全文
0 0
原创粉丝点击