列表

详情


NC203399. 串串翻转

描述

你有一个字符串 S,字符串的下标为从 1 到 n 编号。你需要处理两种操作:
1. 给定x,将字符串中的一段翻转。具体的说,设操作后的串为S',则赋值。保证这是一个合法的字串。
2. 给定y,输出S_y,即字符串 S 的第 y 个字符。
保证 ,即所有的第一种操作坐标严格不减。

输入描述

第一行三个整数 n,m,q.
第二行一个字符串 S.
以下q行,每行两个整数 op, pos, 代表操作的类型和下标。

输出描述

将所有第二类操作的答案连接为一个字符串,并输出这个字符串。

示例1

输入:

5 2 5
abcde
2 1
1 1
2 1
1 4
2 5

输出:

abd

说明:

第一次翻转前,字符串为"abcde"。
第一次翻转后,字符串为"bacde"。
第二次翻转后,字符串为"baced"。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 337ms, 内存消耗: 4332K, 提交时间: 2020-03-22 19:15:26

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int maxn=5e6+10;
int n,m,num,l,r,cnt,id,top;
char s[maxn],sta[maxn],q[maxn],ans[maxn];
int main()
{
	scanf("%d%d%d%s",&n,&m,&num,s+1); l=2e6; r=2e6-1; id=1;
	for (int i=1;i<=m;i++) q[++r]=s[i];
	while (num--)
	{
		int op,lc; scanf("%d%d",&op,&lc);
		if (op==2)
		{
			if (lc<=top) ans[++cnt]=sta[lc];
			else if (lc<=top+m)
			{
				lc-=top;
				if (l>r) ans[++cnt]=q[l-lc+1];else ans[++cnt]=q[l+lc-1];
			}
			else ans[++cnt]=s[lc];
		}
		else
		{
			while (id<lc)
			{
				id++;
				if (l<=r) sta[++top]=q[l++],q[++r]=s[id+m-1];else sta[++top]=q[l--],q[--r]=s[id+m-1];
			}
			swap(l,r);
		}
	}
	for (int i=1;i<=cnt;i++) printf("%c",ans[i]);
return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 235ms, 内存消耗: 3684K, 提交时间: 2020-03-21 08:29:55

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+50;
int n,m,q,p;char s[N],ans[N];bool re;
struct Que{
	int l,r;char a[N];
	void pub(int x){a[++r]=x;}
	void puf(int x){a[--l]=x;}
	void pob(){r--;}
	void pof(){l++;}
	int b(){return a[r];}
	int f(){return a[l];}
}qq;
int main(){
	scanf("%d%d%d%s",&n,&m,&q,s+1);qq.l=1e6+10;qq.r=qq.l-1;
	for(int i=1;i<=m;i++)qq.pub(s[i]);
	for(int i=1,op,x,j=1;i<=q;i++){
		scanf("%d%d",&op,&x);
		if(op==1){
			while(j<x)
				if(re) s[j++]=qq.b(),qq.pob(),qq.puf(s[j+m-1]);
				else s[j++]=qq.f(),qq.pof(),qq.pub(s[j+m-1]);
			re^=1;
		}
		else ans[++p]=x<j||x>=j+m?s[x]:re?qq.a[qq.l+j+m-x-1]:qq.a[qq.l+x-j];
	}
	printf("%s",ans+1);
	return 0;
}

上一题