您的位置:首页 > 其它

bzoj2789.Letters(贪心 && 逆序数)

2015-11-03 10:46 211 查看
有两个长度为 n 的由大写英文字母组成的字符串A, B,问最少需要多少次交换( 相邻两个交换 )才能使 A 变为 B ( 保证可以实现 )

首先的一个想法就是:要想总交换次数最小,A , B 中的相同字母要相距的距离最小( 贪心 )。然后就可以根据 A 中每个字母的位置, 把 B 对应成一个序列,求这个序列的逆序数。

/*
Author: JDD
PROG: bzoj2789.letters
DATE: 2015.11.03
*/

#include <cstdio>
#include <queue>

using namespace std;

const int MAX_N = 1000005;

#define low(x) (x & (-x))
int n, c[MAX_N];
queue<int> q[30];

void insert(int x, int p)
{
for(int i = x; i <= n; i += low(i))
c[i] += p;
}

int query(int x)
{
int ret = 0;
for(int i = x; i > 0; i -= low(i))
ret += c[i];
return ret;
}

void init()
{
scanf("%d", &n);
char s[MAX_N]; scanf("%s", s + 1);
for(int i = 1; i <= n; i ++)
q[s[i] - 'A' + 1].push(i);
}

void doit()
{
char s[MAX_N]; scanf("%s", s + 1);
long long ans = 0;
for(int i = 1; i <= n; i ++){
int p = q[s[i] - 'A' + 1].front(); q[s[i] - 'A' + 1].pop();
insert(p, 1);
ans += i - query(p);
}
printf("%lld\n", ans);
}

int main()
{
freopen("1.in", "r", stdin);
init(); doit();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: