ssoj1046密码pasuwado(树状数组+暴力)

来源:互联网 发布:百度网盘无限试用 mac 编辑:程序博客网 时间:2024/06/14 23:33

题目描述

       哪里有压迫,哪里就有反抗。
       moreD的宠物在法庭的帮助下终于反抗了。作为一只聪明的宠物,他打算把魔法使moreD的魔法书盗去,夺取moreD的魔法能力。但moreD怎么会让自己的魔法书轻易地被盗取?moreD在魔法书上设置了一个密码锁,密码锁上有一个问题。
       施以斯卧铺魔法吧,你有M次机会,如此将得完美密码。
       然后是一串小写字母串。
       moreD的宠物斯卧铺魔法就是施法时的字符串其中相邻两位交换
       而moreD对于完美密码的定义自然是最小字典序了。
       请帮助moreD的宠物,想出密码吧。

输入

第一行一个整数M,表示操作次数。
第二行一串小写字母组成的字符串S,如题目所示。

输出

输出完美密码。

样例输入

3dcba

样例输出

adcb

提示

【数据范围】

       对于30%的数据|S|≤10

对于60%的数据|S|≤3,000

       对于100%的数据8≤|S|≤100,000 M≤(|S|-8)^2+2

【后记】

       宠物最终战胜了moreD,和自己的宠物快乐地生活着。

【样例解释】

       先对第3,4两位施法,字符串变成dcab,然后对第2,3两位施法,字符串变成dacb,最后对第1,2两位施法,字符串变成adcb。


#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <cmath>#include <algorithm>#define ll long longusing namespace std;const int maxn=100005;const int cn=96;int len,fst[31],nxt[maxn];ll sm,n,sum[maxn];char s[maxn];inline ll lowbit(ll x){    return (ll)(x&-x);}inline void add(ll x,ll v){    while(x<len){        sum[x]+=v;        x+=lowbit(x);    }}inline ll getsum(ll x){    ll ans=0;    while(x){        ans+=sum[x];        x-=lowbit(x);    }    return ans;}int main(){    memset(fst,0,sizeof(fst));    memset(nxt,0,sizeof(nxt));    scanf("%lld",&n);    scanf("%s",s+1);    len=strlen(s+1);    for(int i=len;i>=1;--i)nxt[i]=fst[s[i]-cn],fst[s[i]-cn]=i;    for(int i=1;i<=len;++i)add(i,1);    for(int i=1;i<=len;++i){        int j;        for(j=1;j<=26;++j){            int pos=fst[j];            if(pos==0)continue;            sm=getsum(pos-1);            if(n>=sm){                n-=sm;                add(pos,-1);                fst[j]=nxt[pos];                printf("%c",j+cn);                break;            }        }    }    return 0;}


思路:贪心,每次把能加到的最小的往前加。直接暴力会超时,用树状数组维护。

注意:n要用long long还有读入要记得修改!TAT


0 0