題意:給一個字符串,交換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;
}