Finally, you come to the interview room. You know that a Microsoft interviewer is in the room though the door is locked. There is a combination lock on the door. There are N rotators on the lock, each consists of 26 alphabetic characters, namely, ‘A’-‘Z’. You need to unlock the door to meet the interviewer inside. There is a note besides the lock, which shows the steps to unlock it.
Note: There are M steps totally; each step is one of the four kinds of operations shown below:
Type1: CMD 1 i j X: (i and j are integers, 1 <= i <= j <= N; X is a character, within ‘A’-‘Z’)
This is a sequence operation: turn the ith to the jth rotators to character X (the left most rotator is defined as the 1st rotator)
For example: ABCDEFG => CMD 1 2 3 Z => AZZDEFG
Type2: CMD 2 i j K: (i, j, and K are all integers, 1 <= i <= j <= N)
This is a sequence operation: turn the ith to the jth rotators up K times ( if character A is turned up once, it is B; if Z is turned up once, it is A now. )
For example: ABCDEFG => CMD 2 2 3 1 => ACDDEFG
Type3: CMD 3 K: (K is an integer, 1 <= K <= N)
This is a concatenation operation: move the K leftmost rotators to the rightmost end.
For example: ABCDEFG => CMD 3 3 => DEFGABC
Type4: CMD 4 i j(i, j are integers, 1 <= i <= j <= N):
This is a recursive operation, which means:
If i > j:
Do Nothing
Else:
CMD 4 i+1 j
CMD 2 i j 1
For example: ABCDEFG => CMD 4 2 3 => ACEDEFG
输入
1st line: 2 integers, N, M ( 1 <= N <= 50000, 1 <= M <= 50000 )
2nd line: a string of N characters, standing for the original status of the lock.
3rd ~ (3+M-1)th lines: each line contains a string, representing one step.
输出
One line of N characters, showing the final status of the lock.
提示
Come on! You need to do these operations as fast as possible.
样例输入
7 4
ABCDEFG
CMD 1 2 5 C
CMD 2 3 7 4
CMD 3 3
CMD 4 1 7
样例输出
HIMOFIN
#include "iostream"
#include "string"
using namespace std;
const int MAX = 50001;
struct Tree
{
int left, right; //区间
int lch, rch; //左右孩子
int base; //当前字母
int add; //操作2的参数
int delta, inc; //操作4的参数
Tree()
{
add = delta = inc = 0;
}
};
Tree tree[MAX << 2];
string str;
int f[MAX];
int SP = 0;
int len;
int times;
void create(int rt, int left, int right)
{
tree[rt].left = left;
tree[rt].right = right;
//叶子结点
if(left == right)
{
tree[rt].base = str[left] - 'A';
tree[rt].lch = tree[rt].rch = 0;
return;
}
//非叶子结点
tree[rt].base = -1;
tree[rt].lch = rt * 2;
tree[rt].rch = rt * 2 + 1;
//递归构造子树
int mid = (tree[rt].left + tree[rt].right) >> 1;
create(tree[rt].lch, left, mid);
create(tree[rt].rch, mid+1, right);
}
//[left, right]为此次操作的区间
//type为操作类型
//根据type,key为此次操作K或delta
void update(int rt, int left, int right, int key, int type)
{
if(!rt)
return;
if(tree[rt].left > right || tree[rt].right < left)
return;
if(left <= tree[rt].left && tree[rt].right <= right) //完全包含于当前区间
{
//更新当前区间信息
if(type == 1)
{
tree[rt].base = key;
tree[rt].add = tree[rt].delta = tree[rt].inc = 0;
}
else if(type == 2)
{
tree[rt].add += key;
}
else if(type == 4)
{
tree[rt].delta += key + (tree[rt].left - left);
tree[rt].inc ++;
}
}
else
{
//传递当前区间信息
int mid = (tree[rt].left + tree[rt].right) >> 1;
if(tree[rt].base != -1) //叶子
{
tree[tree[rt].lch].base = tree[tree[rt].rch].base = tree[rt].base;
tree[tree[rt].lch].add = tree[tree[rt].rch].add = tree[rt].add;
tree[tree[rt].lch].inc = tree[tree[rt].rch].inc = tree[rt].inc;
tree[tree[rt].lch].delta = tree[rt].delta;
tree[tree[rt].rch].delta = tree[rt].delta + (mid - tree[rt].left + 1) * tree[rt].inc;
}
else //非叶子
{
tree[tree[rt].lch].add += tree[rt].add;
tree[tree[rt].lch].delta += tree[rt].delta;
tree[tree[rt].lch].inc += tree[rt].inc;
tree[tree[rt].rch].add += tree[rt].add;
tree[tree[rt].rch].delta += tree[rt].delta + (mid - tree[rt].left + 1) * tree[rt].inc;
tree[tree[rt].rch].inc += tree[rt].inc;
}
//更新当前区间信息
tree[rt].base = -1;
tree[rt].add = tree[rt].delta = tree[rt].inc = 0;
update(tree[rt].lch, left, right, key, type);
update(tree[rt].rch, left, right, key, type);
}
}
//遍历线段树,产生新的字符串
void getResult(int rt)
{
if(!rt)
return;
if(tree[rt].base != -1) //叶子
{
int delta = tree[rt].delta ;
for(int i=tree[rt].left; i<=tree[rt].right; i++)
{
f[i] = (tree[rt].base + tree[rt].add + delta) % 26;
delta += tree[rt].inc;
}
}
else
{
int mid = (tree[rt].left + tree[rt].right) >> 1;
//lch
tree[tree[rt].lch].add += tree[rt].add;
tree[tree[rt].lch].delta += tree[rt].delta;
tree[tree[rt].lch].inc += tree[rt].inc;
//rch
tree[tree[rt].rch].add += tree[rt].add;
tree[tree[rt].rch].delta += tree[rt].delta + (mid - tree[rt].left + 1) * tree[rt].inc;
tree[tree[rt].rch].inc += tree[rt].inc;
getResult(tree[rt].lch);
getResult(tree[rt].rch);
}
}
void getAns()
{
for(int i=0; i<len; i++)
cout << ((char)(f[(SP+i)%len] + 'A'));
}
int main()
{
int type, left, right, key;
char ch;
string cmd;
cin >> len;
cin >> times;
cin >> str;
create(1, 0, len-1);
while(times--)
{
cin >> cmd;
cin >> type;
if(type == 1)
{
cin >> left; cin >> right; cin >> ch;
key = ch - 'A';
int start = left + SP - 1;
int end = right + SP -1;
if(start < len && end > len)
{
update(1, start, len-1, key, type);
update(1, 0, end-len, key, type);
}
else
{
if(start >= len)
{
start %= len;
end %= len;
}
update(1, start, end, key, type);
}
}
else if(type == 2)
{
cin >> left; cin >> right; cin >> key;
int start = left + SP - 1;
int end = right + SP -1;
if(start < len && end > len)
{
update(1, start, len-1, key, type);
update(1, 0, end-len, key, type);
}
else
{
if(start >= len)
{
start %= len;
end %= len;
}
update(1, start, end, key, type);
}
}
else if(type == 3)
{
cin >> key;
SP += key;
SP %= len;
}
else
{
cin >> left; cin >> right;
int start = left + SP - 1;
int end = right + SP -1;
if(start < len && end > len)
{
update(1, start, len-1, 1, type);
update(1, 0, end-len, len-start+1, type);
}
else
{
if(start >= len)
{
start %= len;
end %= len;
}
update(1, start, end, 1, type);
}
}
}
getResult(1);
getAns();
return 0;
}