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;
    }
    
  • 相关阅读:
    牛客IOI周赛17-提高组 卷积 生成函数 多项式求逆 数列通项公式
    6.3 省选模拟赛 Decompose 动态dp 树链剖分 set
    AtCoder Grand Contest 044 A Pay to Win 贪心
    5.29 省选模拟赛 树的染色 dp 最优性优化
    luogu P6097 子集卷积 FST FWT
    CF724C Ray Tracing 扩展欧几里得 平面展开
    5.30 省选模拟赛 方格操作 扫描线 特殊性质
    5.29 省选模拟赛 波波老师 SAM 线段树 单调队列 并查集
    Spring main方法中怎么调用Dao层和Service层的方法
    Bug -- WebService报错(两个类具有相同的 XML 类型名称 "{http://webService.com/}getPriceResponse"。请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。)
  • 原文地址:https://www.cnblogs.com/Fast-Bird/p/11856547.html
Copyright © 2011-2022 走看看