contest: Codeforces Round #297 (Div. 2), problem: (B) Pasha and String

B. Pasha and String
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Pasha got a very beautiful string s for his birthday, the string consists of lowercase Latin letters. The letters in the string are numbered from 1 to |s| from left to right, where |s| is the length of the given string.

Pasha didn't like his present very much so he decided to change it. After his birthday Pasha spent m days performing the following transformations on his string — each day he chose integer ai and reversed a piece of string (a segment) from position ai to position|s| - ai + 1. It is guaranteed that 2·ai ≤ |s|.

You face the following task: determine what Pasha's string will look like after m days.

Input

The first line of the input contains Pasha's string s of length from 2 to 2·105 characters, consisting of lowercase Latin letters.

The second line contains a single integer m (1 ≤ m ≤ 105) —  the number of days when Pasha changed his string.

The third line contains m space-separated elements ai (1 ≤ ai; 2·ai ≤ |s|) — the position from which Pasha started transforming the string on the i-th day.

Output

In the first line of the output print what Pasha's string s will look like after m days.

Sample test(s)
input
abcdef
1
2
output
aedcbf
input
vwxyz
2
2 2
output
vwxyz
input
abcdef
3
1 2 3
output
fbdcea
-----------------

思路:
转置与顺序无关,比如 1 2 3 4 5 和 5 4 3 2 1的转置顺序结果是一样的,所以先进行排序,删除成对的且相同的,同一部分转置两次相当于没转。
  
其实还可以简化,刚开始嫌麻烦就这样交了..于是超时了..刚好卡在最后一组数据上..
于是要进一步优化,例如一个长度为10的串,输入 5 4 3 2 2 1 先排序,删掉两个2,剩下 1 3 4 5 。
即 1-10,3-8,4-7,5-6  先看前两个,3-8 转了两次,所以只需要转置 1,2 与 9,10 即可。 同理,只要交换 4 与 7 即可。
这样不仅运行次数减少了一半以上,而且每次执行的任务也大大减少了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn1=200000+100,maxn2=100000+100;
char str[maxn1];     ///全局变量!
int a[maxn2];

void reve(int p,int q)   ///第一步优化,不用把数组作为参数加进来了
{
   for(int i=p;i<=(p+q)/2;i++)
   {
      char c=str[i];
      str[i]=str[p+q-i];
      str[p+q-i]=c;
   }
}

void change(int a,int b,int c,int d)    ///第二步优化
{
   for(int i=a;i<=b;i++)
     {
       char c=str[i];
       str[i]=str[a+d-i];
       str[a+d-i]=c;
     }
}


int main()
{
    while(~scanf("%s",str))
    {
        int len=strlen(str);

        int m;
        scanf("%d",&m);
        for(int i=0;i<m;i++)
            scanf("%d",a+i);
        sort(a,a+m);

        for(int i=0;i<m-1;i++)   ///i<m-1
            if(a[i]==a[i+1]&&a[i]!=0)  a[i]=0,a[i+1]=0;   ///a[i]!=0

        int flag=2;
        int k,t;
        for(int i=0;i<m;i++)
        {
            if(a[i])
            {
               if(flag==2) flag--,k=a[i]-1;   ///选出第一个没被删的数
               else if(flag==1) flag--,t=a[i]-1;    ///第二个没被删的数,这两个数一定不相等
            }

            if(!flag) change(k,t-1,len-t,len-k-1),flag=2;   ///优化2
        }
        if(flag==1) reve(k,len-1-k);   /// 是否存在落单的数


        /// for(int i=0;i<m;i++)
           /// if(a[i]) reve(a[i]-1,len-a[i]);

        printf("%s\n",str);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值