描述:
哈特13非常嫌弃字符串,现在他有一个长度为n的字符串,由于嫌弃,所以他要将字符串进行一系列的更改。每次更改选择一个点ai,表示选中它从ai开始到n-ai+1的子串,然后将其首尾翻转,就这样一共翻转了m次,现在他想知道字符串被他玩成什么样子了。 但是他自己太笨并不知道,所以向你求助。 No zuo no die
输入:
多组输入,直到文件末尾 每组数据第一行为字符串,长度1<=n<=100000 第二行为翻转数m,0<=m<=100000 接下来m个数字,每个数字表示翻转起点。
输出:
翻转之后的字符串
样例:
Input xcemt 2 1 2 Output tcemx 分析 xcemt -> tmecx -> tcemx
题解
直接一步一步暴力交换字符必然是会炸的,从题目上面我们可以看出来字符串每一次翻转都是关于中心点对称交换的,所以我们直接统计每一个点需要翻转多少次,最后再O(N)处理即可(奇翻偶不翻)。很容易想到每一次翻转就把m到n-m-1的计数器都+1,但是这样的话时间复杂度一样是 $N^2$,所以这里使用差分进行区间修改(关于差分的运用在这一篇博客有详解 )。
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <bits/stdc++.h> #define LL long long int #define INIT(a,b) memset(a,b,sizeof(a)) #define rep(i,a,b) for(int i=a;i<b;i++) #define per(i,b,a) for(int i=b-1;i>=a;i--) const double Pi = acos (-1 );const double E = exp (1.0 );const LL mod =1e9 +7 ;const int MAX=0x7fffffff ;const int MIN=-0x7fffffff ;const int INF=0x3f3f3f3f ;using namespace std ;int num[100005 ];int main () { ios::sync_with_stdio(false ); string str; while (cin >>str) { INIT(num,0 ); int m,ai; cin >>m; int len=str.size(); while (m--) { cin >>ai; if (ai-1 <=len-ai){ num[ai-1 ]++; num[len-ai+1 ]--; } else { num[ai]--; num[len-ai]++; } } char Str[100005 ];INIT(Str,'\0' ); for (int i=1 ;i<len;i++) num[i]+=num[i-1 ]; for (int i=0 ;i<len;i++) { if (num[i]%2 ==0 )Str[i]=str[i]; else Str[i]=str[len-i-1 ]; } cout <<Str<<"\r\n" ; } return 0 ; }