array array array
题意:有n个数,要求去掉k个数后,剩下的数能构成非递减或者非递增序列,就输出 "A is a magic array.",反之输出"A is not a magic array.";
思路:去掉k个数之后能构成非递增序列则元数列中的LIS的长度不小于n-k,若能构成非递减序列,则原数列的最长递减子序列长度不小于n-k;其实就是求LIS,和最长递减子序列(我称之为ULIS);
用O(nlogn)的算法;
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn], b[maxn], c[maxn], n, k;
int find_first_bigger(int x, int l, int r){
int ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(b[mid]<=x) l=mid+1;
else r=mid-1;
}
return l;
}
int LIS(){
int len=0, pos;
for(int i=0; i<n; i++){
if(len==0||a[i]>b[len]){
b[++len]=a[i];
}
else{
pos=find_first_bigger(a[i], 1, len);
b[pos]=a[i];
}
}
return len;
}
int find_first_less(int x, int l, int r){
while(l<=r){
int mid=(l+r)>>1;
if(c[mid]>=x) l=mid+1;
else r=mid-1;
}
return l;
}
int ULIS(){
int len=0, pos;
for(int i=0; i<n; i++){
if(len==0||a[i]<c[len]){
c[++len]=a[i];
}
else{
pos=find_first_less(a[i], 1, len);
c[pos]=a[i];
}
}
return len;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &k);
for(int i=0; i<n; i++)
scanf("%d", &a[i]);
int len1=LIS(), len2=ULIS();
if(k>=n-len1||k>=n-len2) printf("A is a magic array.\n");
else printf("A is not a magic array.\n");
}
return 0;
}