CodeForces - 1430E - String Reversal (贪心 + 树状数组求逆序数)

简介: 笔记

String Reversal


题意

对于一个字符串 每次可以交换相邻的两个字符 问 最少经过多少次操作后能将原来的字符串倒序


思路

对于样例 aaaza 倒序后应该是 azaaa 从最后一个字符开始看 需要有一个a 移到最后面,因为源字符串中有多个a 显然 把下标最大的a 移到最后花费的操作次数最小


操作前下标12345 操作后下标14235 逆序数恰好为 2 所以大胆假设 不用求证(不是) 本题即为按照上面规得到新的下标然后求逆序数即可 逆序数用树状数组维护


代码

   #include<bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define endl '\n'
using namespace std;
typedef  long long LL;
inline LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; }
inline LL lowbit(LL x) {return x & -x;}
const int N = 200010;
LL n;
string s;
vector<int>v[30];
int temp[30]; //记录每个字母使用到了第几个
LL tr[4 * N];
LL query(LL x) {
  LL res = 0;
  for (int i = x; i ; i -= lowbit(i))res += tr[i];
  return res;
}
void modify(LL x, LL c) {
  for (int i = x; i <= n; i += lowbit(i))tr[i] += c;
}
void solve() {
  cin >> n;
  cin >> s;
  for (int i = n - 1; i >= 0; --i) {
    v[s[i] - 'a'].push_back(i + 1); //存每个字母出现的位置 大的优先
  }
  reverse(s.begin(), s.end());
  LL res = 0;
  for (int i = n - 1; i >= 0; --i) {
    LL x = query(v[s[i] - 'a'][temp[s[i] - 'a']]);
    res += x;
    //cout << "! " << v[s[i] - 'a'][temp[s[i] - 'a']] << endl;
    //cout << "x == " << x << endl;
    modify(v[s[i] - 'a'][temp[s[i] - 'a']], 1);
    temp[s[i] - 'a']++;
  }
  cout << res << endl;
}
int main() {
  //int t; cin >> t;
  //while(t--)
    solve();
  return 0;
}


目录
相关文章
|
存储
poj 3254 Corn Fields (状态压缩dp)
状态压缩dp其实就是用二进制来表示所有的状态,比如这题, 我们在某一行可以这样取0 1 0 1 1 0 1,用1代表取了,0代表没取,因为这点,它的数据量也限制在20以内,所有看到这样数据量的题目可以先考虑一下状态压缩dp。对于有多行的数据,所有状态的总数必然很庞大,而且不用特殊的方法想要存储这些状态是不太现实的。既然每个点只有这两种情况,我们可以用二进制的一位来表示,0 1 0 1 1 0 1就可以表示为二进制0101101也就是十进制的45,如果我们想要枚举6个点的所有状态,我们只需要从0到2^6取其二进制就可以了,并不会重复或是多余。
31 0
|
6月前
|
C++
E. Generate a String(典:贪心+动态规划)
E. Generate a String(典:贪心+动态规划)
|
6月前
|
人工智能 算法 测试技术
map|动态规划|单调栈|LeetCode975:奇偶跳
map|动态规划|单调栈|LeetCode975:奇偶跳
|
6月前
|
算法 机器人
class051 二分答案法与相关题目【算法】
class051 二分答案法与相关题目【算法】
66 0
|
6月前
|
算法 图计算 容器
class050 双指针技巧与相关题目【算法】
class050 双指针技巧与相关题目【算法】
45 0
|
人工智能
poj 2299 Ultra-QuickSort 求逆序数 树状数组解法
所谓离散化,我们的了解就是对原数组排序,然后用所在位置的下标代替原数,这样我们就可以把数据范围缩小到1-500000,这个数组是开的下的。
42 0
LeetCode剑指 Offer 58—左旋转字符串(三次翻转/double+substr)
LeetCode剑指 Offer 58—左旋转字符串(三次翻转/double+substr)
|
Go
POJ 1503 Integer Inquiry 简单大数相加
POJ 1503 Integer Inquiry 简单大数相加
80 0