E. String Reversal

63 篇文章 1 订阅
35 篇文章 1 订阅

题意:
给定一个字符串,你每次可以交换相邻位置的字母,问最少操作多少次才能达到他的反转串
思路:
先把反转串获得,“abcbd"的反转串"dbcba”,然后我们从反转串的最前面开始遍历,由于贪心,我们尽量把在原串中最近出现该字母的位置放到位置上,第一步模拟出来就是"dabcb",对于d后面这些位置也就是消除了影响,模拟下来每一次放到前面的贡献就是现在还在序列中并且在这个位置前并且未被操作的字母的个数,那么用个树状数组维护一下就行了,复杂度O(nlogn)。
代码:

// Problem: E. String Reversal
// Contest: Codeforces - Educational Codeforces Round 96 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1430/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
#define IL inline
#define x first
#define y second
typedef long long ll;
using namespace std;
const int N=200010;
int tr[N];
int n;
int lowbit(int x)
{
	return x&-x;
}
int query(int x)
{
	int res = 0;
	for(int i=x;i;i-=lowbit(i))
		res+=tr[i];
	return res;
}
void add(int x,int d)
{
	for(int i=x;i<=n;i+=lowbit(i))
			tr[i]+=d;
}
queue<int>q[26];
int main()
{
	
	cin>>n;
	string s;
	cin>>s;
	ll res=0;
	s=" "+s;
	for(int i=1;i<s.size();i++)
	{
		q[s[i]-'a'].push(i);
		add(i,1);	}
	for(int i=(int)s.size()-1;i>=1;i--)
	{
		int tt=q[s[i]-'a'].front();
		q[s[i]-'a'].pop();
		res+=query(tt-1);
		add(tt,-1);
	}
	cout<<res<<endl;
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值