题意:给一个字符串,交换m次,每次交换a[i]~n-a[i]+1的字符(例如a[i]=2,n-5,则s[2]和s[4]换)。
思路:暴力时间复杂度是10^5*10^5,pass。在交换中,我们可以先把多余的交换去掉。每个字符交换次数若为偶数,一定不变。为奇数,再交换一次即可。
用f[i]表示[i,n-i-1]段交换次数,n/2之后全部等价成1~n/2的。dp[i]表示每个字符交换的次数。注意字符串长度是奇数还是偶数,需分开讨论!
本题关键是找到每段字符串交换次数与每个字符交换次数的递推关系式:dp[i]=dp[i-1]+f[i]。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cmath>
#define ll __int64
#define INF 0x3fffffff
#define N 2*100005
using namespace std;
char s[N];
int m;
int a[N];
int f[N];//[i,n-i-1]段交换次数
int dp[N];//每位需交换次数
int main()
{
//freopen("d:\\Test.txt","r",stdin);
cin>>s;
cin>>m;
memset(f,0,sizeof(f));
memset(dp,0,sizeof(dp));
int n=strlen(s);
for(int i=0;i<m;i++){
cin>>a[i];
}
if(n%2==0){
for(int i=0;i<m;i++){
if(a[i]<=n/2){
f[a[i]]++;
}else{
f[n-a[i]+1]++;
}
}
dp[1]=f[1];
for(int i=2;i<=n/2;i++){
dp[i]=dp[i-1]+f[i];
}
}
else{
for(int i=0;i<m;i++){
if(a[i]<n/2){
f[a[i]]++;
}else{
f[n-a[i]+1]++;
}
}
dp[1]=f[1];
for(int i=2;i<=n/2;i++){
dp[i]=dp[i-1]+f[i];
}
}
for(int i=0;i<=n/2;i++){
if(dp[i+1]&1) swap(s[i],s[n-i-1]);
}
cout<<s<<endl;
return 0;
}