number(NOIP模拟赛Round 3)

好吧,神奇的题目。。

原题传送门

这道题目,神奇的字符单调栈。。

首先预处理出1~n个数(大家都会。)

然后塞进字符串里,输出答案(水~)

然后。。

我们需要将所有的字符存入单调栈中,然后乱搞,就可以输出啦。

不过注意:有的题目可能在单调栈中没有把所有的字符删完,即后面的所有字符都一样,那么此时我们需要直接把后面的多出来的位数减去即可。

还有,单调栈中如果已经减了m位之后就不能再减了

在维护单调队列时我们要尽量让排名靠前的数字被删除(贪心)

这样得到的答案才最优

(这道题我一开始做的时候没有维护单调队列,而是维护上升子序列,导致一部分(80)的点WA,我的锅。。。)

果然还是我太弱了。。

%180 Rank 1的大神zxyer

下面贴代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int k,m;
unsigned long long num[30050];
unsigned long long qaq[11];
int num1=-1,num2=-1;
char ans1[1000005];
char zc[1000005];
char ans[1000005];
int main(){
    //freopen("number.in","r",stdin);
    //freopen("number.out","w",stdout);
    memset(ans,0,sizeof(ans));
    memset(ans1,0,sizeof(ans1));
    scanf("%d%d",&k,&m);
    int tot=1;
    num[1]=1;
    int tail1=1,tail2=1;
    while(k>tot)
    {
        if(num[tail1]*2+1>num[tail2]*4+5)num[++tot]=num[tail2]*4+5,tail2++;
        else num[++tot]=num[tail1]*2+1,tail1++;
    }
    int tt=-1;
    for(int i=1;i<=k;i++)
    {
        tt=-1;
        while(num[i])
        {
            int tmp=num[i]%10;
            qaq[tmp]++;
            zc[++tt]=tmp+48;    
            num[i]/=10;
        }
        for(int i=tt;i>=0;i--)
        ans1[++num1]=zc[i];
    }
    printf("%s
",ans1);
    int cnt=0;
    int total=m;
    for(int i=0;i<=num1;i++)
    {
        while(m&&cnt&&ans1[i]>ans[cnt])cnt--,m--;
        ans[++cnt]=ans1[i];
    }
    if(cnt>num1-total+1)cnt=num1-total+1;
    for(int i=1;i<=cnt;i++)
    printf("%c",ans[i]);
    printf("
");
    return 0;
    //fclose(stdin);
    //fclose(stdout);
}
原文地址:https://www.cnblogs.com/ghostfly233/p/6901033.html