zoukankan      html  css  js  c++  java
  • CSP 2019.11.14 密码

    题目描述

    哪里有压迫,哪里就有反抗。
    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。

    一眼望过去

    很明显是个贪心啊,要求在一定的步骤内通过两两交换使得字典序最小.

    解法

    针对30%的数据:
    暴力dfs。
    针对60%的数据:
    贪一下心吧。由于题目要求字典序,可以贪心地从前到后确定每一位的字母。字母肯定是从小到大地枚举,操作距离内的枚举字母的话肯定会贪心地把这个字母换入目标位置。而选择枚举的字母就是贪心地选择尽量前的字母。
    针对100%的数据:
    每次找每种字母最前的那个,再对他进行往前移,这样可以用最小的步骤。可以用vector或链表。然后我们要统计交换的代价,因为是动态改变的,我们就可以用数据结构来维护,比如树状数组或线段树.

    参考代码

    #include<bits/stdc++.h>
    const int N=1e5+10;
    typedef long long ll;
    using namespace std;
    int n;
    int top[26];
    ll m,tre[N];
    char s[N],ans[N];
    vector<int>f[26];
    inline int lowbit(int k){
    	return k&(-k);
    }
    inline void add(int k,int v) {
    	for(int i=k; i<=n; i+=lowbit(i)) tre[i]+=v;
    }
    inline ll ask(int i) {
    	ll sum=0;
    	while(i) {
    		sum+=tre[i];
    		i-=lowbit(i);
    	}
    	return sum;
    }
    int main() {
    	freopen("pasuwado.in", "r", stdin);
    	freopen("pasuwado.out", "w", stdout);
    	cin>>m;
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	for(int i=1; i<=n; i++) {
    		f[s[i]-'a'].push_back(i);
    		if(i==1) add(i,0);
    		else add(i,1);
    	}
    	for(int i=1; i<=n; i++) {
    		for(int j=0; j<26; j++) {
    			if(top[j]>=f[j].size()) continue;
    			int t=f[j][top[j]];
    			ll cost=ask(t);
    			if(cost<=m) {
    				m-=cost;
    				add(t+1,-1);
    				top[j]++;
    				ans[i]=j+'a';
    				break;
    			}
    		}
    	}
    	for(int i=1; i<=n; i++) printf("%c",ans[i]);
    	cout<<endl;
    	return 0;
    }
    
  • 相关阅读:
    hbase
    2013年实习
    Distinct Subsequences
    LumiSoft
    Implicit super constructor xx() is undefined for default constructor. Must define an explicit constructor
    XmlDocument.LoadXml和Load的区别
    应输入 #endregion 指令报错的排查技巧
    c#删除list中的元素
    Dragon Balls(hdu3635带权并查集)
    Java实现 蓝桥杯 算法训练 寻找数组中最大值
  • 原文地址:https://www.cnblogs.com/Fast-Bird/p/11856547.html
Copyright © 2011-2022 走看看