array array array-- 2017 ACM/ICPC Asia Regional Shenyang Online

Kaitou Kiddo 向侦探 Conan 提出了一个数学谜题:如何通过删除最多 k 个元素使得数组变为单调递增或递减。本文提供了一个高效算法解决方案,使用改进的二分查找来确定是否可以实现这一目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Description
One day, Kaitou Kiddo had stolen a priceless diamond ring. But detective Conan blocked Kiddo's path to escape from the museum. But Kiddo didn't want to give it back. So, Kiddo asked Conan a question. If Conan could give a right answer, Kiddo would return the ring to the museum.
Kiddo: "I have an array A and a number k, if you can choose exactly k elements from A and erase them, then the remaining array is in non-increasing order or non-decreasing order, we sayA is a magic array. Now I want you to tell me whether A is a magic array. " Conan: "emmmmm..." Now, Conan seems to be in trouble, can you help him?
 

Input
The first line contains an integer T indicating the total number of test cases. Each test case starts with two integersn and k in one line, then one line with n integers: A1,A2An.
1T20
1n105
0kn
1Ai105
 

Output
For each test case, please output "A is a magic array." if it is a magic array. Otherwise, output "A is not a magic array." (without quotes).
 

Sample Input
3 4 1 1 4 3 7 5 2 4 1 3 1 2 6 1 1 4 3 5 4 6
 

Sample Output
A is a magic array. A is a magic array. A is not a magic array.
解析:此题换位思考就是要求给定的数组的最长递增序列或者是最长递减序列,倘若要是用线性DP的话绝对会超时,所以这题运用了改进的二分查找的办法,这样就会使时间复杂度在O(nlogn);
#include"iostream"
using namespace std;

int ai[101100];
int ci[101100];
int bi[101100];
int n;

int lis1(int ai[101100])
{
    bi[0]=-10000;//把B[0]设为最小,假设任何输入都大于-10000;
    bi[1]=ai[0];//初始时,最大递增子序列长度为1的最末元素为a1
    int Len = 1;//Len为当前最大递增子序列长度,初始化为1;
    int p,r,m;//p,r,m分别为二分查找的上界,下界和中点;
    for(int i = 1;i<n;i++)
    {
        p=0;r=Len;
        while(p<=r)
        //二分查找最末元素小于ai+1的长度最大的最大递增子序列;
        {
        m = (p+r)/2;
        if(bi[m]<ai[i]) p = m+1;
        else r = m-1;
        }
        bi[p] = ai[i];//将长度为p的最大递增子序列的当前最末元素置为ai+1;
        if(p>Len) Len++;//更新当前最大递增子序列长度;
    }
    return Len;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int k;
        cin>>n>>k;
        for(int i=0;i<n;i++)
        {
            cin>>ai[i];
        }
        for(int i=0;i<n;i++)
        {
            ci[i]=ai[n-i-1];
        }
        int num=lis1(ai);
        int num1=lis1(ci);
        if(max(num,num1)+k>=n) 
            cout<<"A is a magic array."<<endl;
        else
            cout<<"A is not a magic array."<<endl; 
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值