Portal
Time limit:10000msSingle Point time limit:1000msMemory Limit:256MBDescribe
Finally, you come to the interview. You know a Microsoft interviewer are in the though the door is locked. There is a combination lock on the door. There is N rotators on the lock, each consists of 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 is M steps totally; Each step was 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 was 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 is all integers, 1 <= i <= J <= N)
This was a sequence operation:turn the ith to the jth rotators up K times (if character A was turned up once, it was B; if Z is turned up once, it's A now. )
For EXAMPLE:ABCDEFG = CMD 2 2 3 1 = ACDDEFG
Type3: CMD 3 K: (k is an integer, 1 <= K <= N)
This was 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 is integers, 1 <= i <= J <= N):
This is a recursive operation, which means:
If i > J:do nothingelse:cmd 4 i+1 jcmd 2 I J 1
For EXAMPLE:ABCDEFG = CMD 4 2 3 = ACEDEFG
Input
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.
Output
One line of N characters, showing the final status of the the lock.
Tips
Come on! You need to do these operations as fast as possible.
-
Sample input
-
7 4ABCDEFGCMD 1 2 5 ccmd 2 3 7 4CMD 3 3CMD 4 1 7
-
Sample output
-
Himofin
Analysis:
cmd 1 and
cmd 2 are bare segment trees.
cmd 4 looks very "scary", careful analysis is not difficult to find
CMD 4
i-j is the password to lock the i-bit rotation (turn up) 1 times, the i+1 bit rotation 2 times, the first i+1 bit rotation 3 times, ... This can also be maintained with a line segment tree. for ease of expression, we use delta[i] to represent the turn up times caused by
CMD 4 on position I. the practice is to add two attribute for each node in the segment tree (L, R): One is delta, which is used to record delta[l], and the other is an inc that records the value of delta[i+1]-delta[i] in that interval. It should be noted that when the 1th CMD 4 operation is performed on an interval (node) on a segment tree, its delta value is 1,inc value is 1, followed by the 2nd operation, its delta value is 2,inc value is 2. Consider the following
cmd 3,
cmd 3 k is actually the string (that is, the password is still in the construction) loop left K bit, for example, "ABCDEFG" after the
cmd 3 3 operation, it becomes "defgabc". This kind of operation seems to be contrary to the spirit of the line-segment tree. Segment Tree maintenance is always a string that has not been shifted, and the Wakahara string has already accumulated the left shift s bit, so we just move the s bit to the right of the operation interval corresponding to the current (new) string (note: [L, R] may split into two segments after the right shift), and then it is updated in the line-segment tree.
implementation:Paste the code first, then pits later.
#include <bits/stdc++.h>using namespacestd;Const intN (5e4+5);intsame[n<<2], rot[n<<2], delta[n<<2], inc[n<<2];CharS[n];voidBuildintIdintLintR) { if(L==R) {same[id]=s[l]-'A';return;} intMid= (l+r) >>1; Same[id]=-1; Build (ID<<1, L, mid); Build (ID<<1|1, mid+1, R);}voidCLEAR (intIdintv) {Same[id]=v, rot[id]=delta[id]=inc[id]=0;}voidPush_rot (intSintf) {Rot[s]+=ROT[F], rot[s]%= -;}voidPush_inc (intSintFintd) {Delta[s]+=d, Inc[s]+=inc[f], delta[s]%= -, inc[s]%= -;}voidPush_down (intIdintLintR) { intls=id<<1, rs=ls|1; if(~same[id]) Clear (LS, same[id]), clear (RS, Same[id]), same[id]=-1; if(Rot[id]) Push_rot (LS, id), Push_rot (RS, id), rot[id]=0; intMid= (r+l) >>1, t=delta[id]+ (mid+1-L) *Inc[id]; Push_inc (LS, id, delta[id]), Push_inc (RS, id, T% -), delta[id]=inc[id]=0;}intQueryintIdintLintRintp) { if(~same[id])return(same[id]+rot[id]+delta[id]+ (p-l) *inc[id])% -; Push_down (ID, L, R); //Error-prone intMid= (l+r) >>1; if(P<=mid)returnQuery (id<<1, L, Mid, p); returnQuery (id<<1|1, mid+1, R, p);}voidSET (intIdintLintRintLintRintv) { if(L<=l && r<=R) {CLEAR (id, v); return; } push_down (ID, L, R); intMid= (l+r) >>1; if(L<=mid) SET (id<<1, L, Mid, L, R, v); if(R>mid) SET (id<<1|1, mid+1, R, L, R, v);}voidROTATE (intIdintLintRintLintRintv) { if(L<=l && r<=r) {rot[id]+=v, rot[id]%= -;return;} Push_down (ID, L, R); intMid= (l+r) >>1; if(L<=mid) ROTATE (id<<1, L, Mid, L, R, v); if(R>mid) ROTATE (id<<1|1, mid+1, R, L, R, v);}voidInc_shift (intIdintLintRintLintRintv) { if(L<=l && r<=R) {Delta[id]+=v+l-l;//Error-proneinc[id]+=1; Delta[id]%= -, inc[id]%= -; return; } push_down (ID, L, R); intMid= (l+r) >>1; if(L<=mid) Inc_shift (id<<1, L, Mid, L, R, v);//Error-prone if(R>mid) Inc_shift (id<<1|1, mid+1, R, L, R, v);}intMain () {intN, M; CIN>>n>>m>>s; Build (1,0, N-1); Charch; intshift=0;//Number of left shift for(intT, L, R, K; m--; ) {scanf ("%*s%d", &t); if(t!=3) Cin>>l>>r, l--, R--, l= (l+shift)%n, r= (r+shift)%N; if(t==1) {cin>>ch, k=ch-'A';//cin ignores leading spaces. if(L<=R) SET (1,0, N-1, L, R, K); ElseSET (1,0, N-1, L, N-1, k), SET (1,0, N-1,0, R, K); } Else if(t==2) {cin>>K; if(L<=R) ROTATE (1,0, N-1, L, R, K); ElseROTATE (1,0, N-1, L, N-1, k), ROTATE (1,0, N-1,0, R, K); } Else if(t==3) {cin>>k, Shift+=k, shift%=N; } Else{ if(L<=R) Inc_shift (1,0, N-1, L, R,1); ElseInc_shift (1,0, N-1, L, N-1,1), Inc_shift (1,0, N-1,0, R, n-l+1); } } for(intI=0; i<n; i++) Putchar (query (1,0, N-1, (I+shift)%n) +'A'); Puts (""); return 0;}
Implementation Details:
The code of this problem is relatively large, and in some places it is easy to think clearly.
Let's summarize the segment tree:
The segment tree is used to maintain interval modifications (also known as update/modify/update) and query. Changes and queries can be divided into two categories: point modification, Interval modification, point query, interval query.
The interval modification often uses the Lazy-tag technique. All Atrribute maintained by a segment tree node are all related to the interval of the node and, broadly speaking, can be considered as interval functions.
$f ([L, R]) $. The information of these attribute records can be divided into two categories, one of which is a property of the interval, and the other is some kind of operation on the interval (already).
Besides, the realization of this problem:
The atrribute required for each node of the segment tree, in addition to the Delta, Inc mentioned in the analysis,
- Same, which is used to record the CMD 1 operation experienced by this interval, we use 0~25 to represent ' A ' ~ ' Z ';
- Rot, which is used to record the CMD 2 operation experienced by the interval;
Hihocoder #1058 Combination Lock