首页 > 代码库 > 【noip模拟赛】 射击

【noip模拟赛】 射击

这题似乎是什么安阳一中的模拟题,不管了,反正是学长出的noip模拟赛里面的题目。。。。

射击(shoot.pas/.c/.cpp

时间限制:1s,内存限制128MB

题目描述:

据史书记载,对越反击战时期,有位中国侦察兵,他的代号叫814。一天他执行狙击任务,他的任务地区是n座恰巧在一条直线上的山。这些山所在直线恰巧为东西走向,山从东到西依次编号为1~n。一天814隐藏在编号为k的山上,每座山上都有1个目标。

814也非常的厉害,任务结束时杀了很多人,可是史书中只记载了两点:

1814一定攻击了位于k号山上的目标。

2:所有被814杀死的目标所在山峰刚好从东向西高度严格递增。

请你计算:814最多杀死了多少目标。

输入描述:

第一行为两个整数N,K

接下来是N个整数,依次表示1~n号山的高度hi

输出描述:

814最多杀死的目标数。

样例输入:

8 6

65 158 170 299 300 155 207 389

样例输出:

4

数据范围:

30%的数据保证:0<n<=10000<k<=n

100%的数据,满足0<n<=2000000<k<=n

所有数据保证h<50000

最长上升子序列O(nlogn)算法

 

O(nlogn)的算法关键是它建立了一个数组temp[],temp[i]表示长度为i的不下降序列中结尾元素的最小值,用top表示数组目前的长度,算法完成后top的值即为最长不下降子序列的长度。
设当前的以求出的长度为top,则判断num[i]和temp[top]:
1.如果num[i]>=temp[top],即num[i]大于长度为top的序列中的最后一个元素,这样就可以使序列的长度增加1,即top++,然后现在的temp[top]=num[i];
2.如果num[i]<temp[top],那么就在temp[1]...temp[top]中找到最大的j,使得temp[j]<num[i],然后因为temp[j]<num[i],所以num[i]大于长度为j的序列的最后一个元素,那么就可以更新长度为j+1的序列的最后一个元素,即temp[j+1]=num[i]。

 

 

 

本题算法:

 

这道题数据范围很坑!20W需要用nlogn算法,而nlogn的算法。。。。现学现卖吧。。。

我的做法有点取巧,卡时过的。。。

先做个过滤操作:前k个大于等于第k个的,过滤掉,后(n-k)个小于等于第k个的,过滤掉

然后。。。跑两遍最长上升子序列就OK啦。。

代码:

#include<cstring>#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;int f[200005];int num[200005];int temp[200005];int n,i,j,x,k;int top,ans;bool b[200005]={1};int binary_search(int x){    int mid,l=1,r=top;    while (l<=r)    {        mid=(l+r)>>1;        if (temp[mid]>=x) r=mid-1;        else        {            l=mid;            if (temp[l+1]>=x) return (l+1);                         else l++;        }        }    return 0;}void reworking(){    for (int i=1;i<=k-1;i++)    { if (num[i]>=num[k]) b[i]=false;}        for (int i=k+1;i<=n;i++)    { if (num[i]<=num[k]) b[i]=false;}}int main(){    freopen("shoot.in","r",stdin);    freopen("shoot.out","w",stdout);    for (i=1;i<=200000;i++) {b[i]=true;temp[i]=600000;}    cin>>n>>k;    for (i=1;i<=n;i++)cin>>num[i];    reworking();        memset(temp,0,sizeof(temp));    top=1; int tmp=1;    while (b[tmp]==false) tmp++;    temp[1]=num[tmp];    for (i=2;i<=k-1;i++)    {        if (b[i]==true)        {        if (num[i]>temp[top]) {temp[++top]=num[i];}        else         {            if (num[i]<temp[1]) temp[1]=num[i];            else             {                int j=binary_search(num[i]);                temp[j]=num[i];            }        }        }    }    ans=top;    memset(temp,0,sizeof(temp));    top=1;tmp=k+1;    while (b[tmp]==false) tmp++;    temp[1]=num[tmp];    for (i=k+2;i<=n;i++)    {        if (b[i]==true)        {        if (num[i]>temp[top]) {temp[++top]=num[i];}        else         {            if (num[i]<temp[1]) temp[1]=num[i];            else             {                int j=binary_search(num[i]);                temp[j]=num[i];            }        }        }    }    ans=ans+top;    cout<<ans+1<<endl;    return 0;}

结果