您的位置:首页 > 其它

密码 pasuwado题解

2015-09-18 17:20 281 查看

题目描述

哪里有压迫,哪里就有反抗。

moreD的宠物在法庭的帮助下终于反抗了。作为一只聪明的宠物,他打算把魔法使moreD的魔法书盗去,夺取moreD的魔法能力。但moreD怎么会让自己的魔法书轻易地被盗取?moreD在魔法书上设置了一个密码锁,密码锁上有一个问题。

施以斯卧铺魔法吧,你有M次机会,如此将得完美密码。

然后是一串小写字母串。

moreD的宠物斯卧铺魔法就是施法时的字符串其中相邻两位交换。

而moreD对于完美密码的定义自然是最小字典序了。

请帮助moreD的宠物,想出密码吧。

输入

第一行一个整数M,表示操作次数。

第二行一串小写字母组成的字符串S,如题目所示。

输出

输出完美密码

样例输入

3

dcba

样例输出

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。


想法

可以贪心的选取合法位置的字典序最小的移到前面

可以想到一些数据结构来实现(Splay或者链表+树状数组)

算法

从小到大枚举第一位的字母

并用树状数组维护每个字母的位置

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
ll M;
int len;
int C[100005],next[100005],head[26];
char S[100005];
inline void add(int x,int pos)
{
next[pos]=head[x]; head[x]=pos;
}
inline void update(int x,int v)
{
for(int i=x;i<=len;i+=i&-i) C[i]+=v;
}
inline int query(int x)
{
if(x==0) return 0;
int res=0;
for(int i=x;i>0;i-=i&-i) res+=C[i];
return res;
}
int main()
{
scanf("%lld",&M);
scanf("%s",&S);
len=strlen(S);
for(int i=len-1;i>=0;i--) add(S[i]-'a',i+1);
for(int i=1;i<=len;i++) update(i,1);
for(int i=0;i<len;i++)
{
int j;
for(j=0;j<26;j++)
{
int tmp;
if(head[j]!=0&& (tmp=query(head[j]-1))<=M)
{
M-=tmp;
update(head[j],-1);
head[j]=next[head[j]];
break;
}
}
printf("%c",j+'a');
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: