导弹拦截-最长不下降子序列和不下降子序列个数-nlogn算法
1.最长不下降子序列求法(我还没吃透,处于看懂觉得牛逼但是自己想不到的情况)
2.不下降子序列的个数
分析:
假设现在有n个序列了
当遇到一个新数时,只要之前任意一个序列的最小数比它高,就可以把它放进来了
那么它该插入哪个序列呢?如果插入最小数最大的序列(最小数为x)后面,下次遇到比较大但是又没有x大的数,就没办法插入了
我管这叫做浪费,因为小数就可以杀掉的怪你非得大数杀
所以应该插入它能插入的数中最小的数
即开一个数组序列的最小数,找到大于等于它的序列中最小数,代替这个数(这样看来应该弄一个优先队列??->不用,一边一定一比该数大于等于,一边一定比该数小,顺序无误)
4.输入
while(scanf("%d", &t)!=EOF)
或者
#include<iostream> #include<cstdio> #include<algorithm> #define R register using namespace std; const int N=100010; int a[N],d1[N],d2[N],n; inline bool read(int &x) { char c=getchar(); if(c==EOF)return false; while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9') { x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return true; } int main() { while(read(a[++n]));n--; R int len1=1,len2=1; d1[1]=d2[1]=a[1]; for(R int i=2; i<=n; i++) { if(d1[len1]>=a[i])d1[++len1]=a[i]; else *upper_bound(d1+1,d1+1+len1,a[i],greater<int>())=a[i]; if(d2[len2]<a[i])d2[++len2]=a[i]; else *lower_bound(d2+1,d2+1+len2,a[i])=a[i]; } printf("%d\n%d",len1,len2); return 0; }
5.AC题解
#include <iostream> #include <algorithm> using namespace std; const int N = 1e5+10; int a[N], b[N]; int main() { int t; scanf("%d", &t); int len1 = 1, len2 = 1; a[1] = b[1] = t; while(scanf("%d", &t)!=EOF) { if(t<=a[len1]) a[++len1]=t; else { int pos = upper_bound(a+1,a+1+len1,t, greater<int>())-a; a[pos] = t; } if(t>b[len2]) b[++len2]=t; else { int pos = lower_bound(b+1, b+1+len2,t)-b; b[pos] = t; } } printf("%d %d\n", len1, len2); return 0; }

浙公网安备 33010602011771号