暴力赛高!暴力是全世界最最最(以下省略2147483647个人最)NB的算法!
这里似乎没有朴素的算法啊(啊当然Pascal不算哈)
我开始做题的时候还专门为了求稳去学习了一下nlogn的最长上升子序列呢
其实我们会发现,暴力的时间复杂度其实根本不是O(n2),就让我们来分析一下暴力的时间复杂度。
首先,读入,时间复杂度O(n+k),即O(n);
接下来,对必须做题的时间排序,复杂度O(nlogn);
再下去,对每段进行最长上升子序列,在一般情况下ci平均分布,复杂度为O((n/k)2∗k),即O(n2/k),但是,在某些奇葩的数据下,会出现这个复杂度退化为O(n2)的情况,显然,这道题并没有这样的数据(啊当然NOIP的话你是可以看看CCF会不会出这种毒瘤数据,但是这种一般的题目出题人都是直接敲个随机生成就走人的)(不要问我为什么因为我自己出题就是这么干的)。
综上所述,暴力的时间复杂度为O(n2/k),似乎AC并没有多少问题。。。
上代码,具体的问题就看代码辣~~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include<bits/stdc++.h> // 万能头文件
using namespace std;
bool cmp(int a, int b){ return a < b; }
int Num[1100000]; int f[1100000];
int Get(int l, int r){ int Lbound = Num[l]; int Rbound = Num[r]; for(int i = l+1; i < r; i++){ if(Num[i] > Lbound && Num[i] < Rbound){ f[i] = 1; for(int j = l+1; j < i; j++){ if(f[j] + 1 > f[i] && Num[j] < Num[i]) f[i] = f[j]+1; } } } int Ans = 0; for(int i = l+1; i < r; i++){ if(f[i] > Ans) Ans = f[i]; } return Ans; }
int main(){ memset(f, 0, sizeof(f)); int n, k; scanf("%d %d", &n, &k); int OI[500000]; for(int i = 1; i <= k; i++){ scanf("%d", &OI[i]); } sort(OI+1, OI+k+1, cmp); for(int i = 1; i <= n; i++){ scanf("%d", &Num[i]); } Num[0] = -1; int Ans = k + Get(0, OI[1]); for(int i = 1; i < k; i++){ Ans += Get(OI[i], OI[i+1]); if(Num[OI[i]] >= Num[OI[i+1]]){ printf("impossible"); return 0; } } Num[n+1] = 2147483647; Ans += Get(OI[k], n+1); if(OI[1] == 0) Ans--; printf("%d", Ans); return 0; }
|