ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【2020NOI.AC省选模拟】C. 送分题

2020-06-02 19:51:45  阅读:246  来源: 互联网

标签:AC ch 省选 mid 2020NOI 序列 include RI define


题目链接

原题解:

从前往后扫描序列,维护当前可能出现在答案中的候选序列。

每当我们遇到一个不在候选序列中的数$x$时,若当前序列中最后一个数$y$在未被扫描得部分中也出现过,且$y>x$,我们可以把$y$弹出候选序列。

重复此操作,然后把$x$加入候选队列。每个元素最多进栈出栈一次,时间复杂度为$O(n)$。

补充:

描述一个我的半暴力的做法。

设置一个序列$s$,初始在每种数最后出现的位置填$0$,其他填$0$。

尝试找$k$轮,每轮找出接下来填的数字。

用树状数组求$s$的后缀和来二分,找出后缀和最大的下标中最靠后的,设为$p$。

设上一次取数的位置为$pre$,那么本轮就可以在$[pre+1,p]$中暴力找最小的数字中的第一个,然后把它在$s$上的影响消去。

这个做法可以AC,但是用时1600ms,算最慢的一档。其他的算法有700ms,1000ms和1300ms三档。

这个复杂度乍一看不太对,因为我们每次会暴力在一个区间里找最小值。

仔细思考一下,说不出个所以然来,但感觉这个暴力找的区间长度和重合度都不会特别高……之类的?然后就能过。不过NOI.AC的数据强度不敢特别恭维……

 

代码(100分):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define IL inline
#define RG register
#define _1 first
#define _2 second
using namespace std;
#define RI RG int
#define RC RG char
const int N=2e6;

IL void qr(RI &x){
    x=0;    RC ch=getchar();
    while(!isdigit(ch))    ch=getchar();
    for(;isdigit(ch);ch=getchar())    x=(x<<3)+(x<<1)+ch-'0';
}

IL void qw(RI x,RC ch){
    RI k=0,s[13];
    for(;x;x/=10)    s[++k]=x%10;
    for(;k;k--)    putchar(s[k]+'0');
    putchar(ch);
}

    int n,k,a[N+3];
    int v[N+3];
    int s[N+3];

IL int lowbit(RI x){return x&(-x);}

IL void mdf(RI p,RI x){
    p=n-p+1;
    for(;p<=n;p+=lowbit(p))
        s[p]+=x;
}

IL int qry(RI p){
    p=n-p+1;
    RI ret=0;
    for(;p;p-=lowbit(p))
        ret+=s[p];
    return ret;
}

IL int sol(RI x){
    RI l=1,r=n,mid,ans;
    while(l<=r){
        mid=(l+r)>>1;
        if(qry(mid)>=x){
            l=mid+1;    ans=mid;
        }
        else 
            r=mid-1;
        
    }
    return ans;
    
}

    int ans[N+3];

int main(){
    qr(n);    qr(k);
    for(RI i=1;i<=n;i++)
        qr(a[i]);
        
    for(RI i=n;i>=1;i--)
    if(!v[a[i]]){
        v[a[i]]=i;
        mdf(i,1);
        
    }
    
    a[n+1]=k+1;
    for(RI i=1,p,x,pre=0;i<=k;i++){
        p=sol(k-i+1);
        x=n+1;
        for(RI j=pre+1;j<=p;j++)
        if(v[a[j]]&&a[j]<a[x])
            x=j;
        ans[i]=a[x];
        mdf(v[a[x]],-1);
        v[a[x]]=0;
        pre=x;
        
    }
    
    for(RI i=1;i<=k;i++)
        qw(ans[i],' ');
    
    return 0;

}
View Code

 

标签:AC,ch,省选,mid,2020NOI,序列,include,RI,define
来源: https://www.cnblogs.com/Hansue/p/13032004.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有