Educational Codeforces Round 96 (Rated for Div. 2) E. String Reversal 题解(思维+逆序对)

题目链接

题目大意

给你一个长度为n的字符串,可以交换相邻两个元素,使得这个字符串翻转,求最少多少种次数改变

题目思路

如果要求数组排序所需要的冒泡次数,那其实就是逆序对

这个也差不多,但是如果是相同字符,用的应该是对应的最近的这个字母。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
int n,cnt[30],ans[maxn],tree[maxn<<2];
char s[maxn];
vector<int> pos[30];
int query(int node,int L,int R,int l,int r){
	if(L<=l&&r<=R){
		return tree[node];
	}
	int mid=(l+r)>>1,sum=0;
	if(mid>=L) sum+=query(node<<1,L,R,l,mid);
	if(mid<R) sum+=query(node<<1|1,L,R,mid+1,r);
	return sum; 
}
void update(int node,int l,int r,int pos){
	if(l==r){
		tree[node]++;
		return ;
	}
	int mid=(l+r)>>1;
	if(mid>=pos) update(node<<1,l,mid,pos);
	else update(node<<1|1,mid+1,r,pos);
	tree[node]=tree[node<<1]+tree[node<<1|1];
}
int main(){
	scanf("%d %s",&n,s+1);
	for(int i=1;i<=n;i++){
		int x=s[i]-'a'+1;
		pos[x].push_back(n-i+1);
	}
	for(int i=n;i>=1;i--){
		int x=s[i]-'a'+1;
		ans[i]=pos[x][cnt[x]++];
	}
	ll pr=0;
	for(int i=1;i<=n;i++){
		int bug=query(1,1,ans[i],1,n);
		pr+=query(1,ans[i],n,1,n);
		update(1,1,n,ans[i]);
	}
	printf("%lld\n",pr);
	return 0;
} 
posted @ 2020-10-15 18:45  hunxuewangzi  阅读(110)  评论(0编辑  收藏  举报