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;
}
不摆烂了,写题