Problem:
Array Update 2

Problem

項数 N 、初項 a 、公差dの等差数列 A がある。
以下の形式で、数列を書き換える M 個の命令文が与えられるので、与えられた順序で M 回
数列 A を書き換えたときの数列 A の K項目の値を求めなさい。

i 番目の命令文は3つの整数 xi , yi , zi で与えられる。(1 ≤ i ≤ M)

xiが0だった場合、yi項目から
zi項目までの区間において、値の順序を反転する。

xiが1だった場合、yi項目から
zi項目までの区間において、それぞれの値を1増加させる。

xiが2だった場合、yi項目から
zi項目までの区間において、それぞれの値を半分にする（小数点以下は切り捨てる）。

Input

N
a d
M
x1 y1 z1
x2 y2 z2
...
xM yM zM
K

1行目に、1つの整数 N が与えられる。
2行目に、2つの整数 a と d が空白区切りで与えられる。
3行目に、1つの整数 M が与えられる。

4行目からの M 行のうち i 行目には i 番目の命令文を表す 3 つの整数 xi, yi, zi が空白区切りで与えられる。

最後の行に、1つの整数 K が与えられる。

Constraints

2 ≤ N ≤ 200000

1 ≤ a ≤ 5

1 ≤ d ≤ 5

1 ≤ M ≤ 200000

0 ≤ xi ≤ 2 (1 ≤ i ≤ M)

1 ≤ yi ≤ N (1 ≤ i ≤ M)

1 ≤ zi ≤ N (1 ≤ i ≤ M)

yi < zi (1 ≤ i ≤ M)

1 ≤ K ≤ N

Output

入力で与えられた順番で数列AをM回更新したときのK項目を出力せよ。

Sample Input 1

4
2 1
3
0 1 2
1 1 4
2 2 4
3

Sample Output 1

2

{ 2 , 3 , 4 , 5 }

↓ 0 1 2 ... 1項目から2項目までの区間の値の順序を反転する

{ 3 , 2 , 4 , 5 }

↓ 1 1 4 ... 1項目から4項目までの区間の値をそれぞれ1増やす

{ 4 , 3 , 5 , 6 }

↓ 2 2 4 ... 2項目から4項目までの区間の値をそれぞれ半分にする（小数点以下切り捨てる）

{ 3 , 1 , 2 , 3 }

よって3項目の値は2である。

Sample Input 2

5
1 2
3
1 2 3
2 3 5
0 1 5
1

Sample Output 2

4

{ 1 , 3 , 5 , 7 , 9 }

↓ 1 2 3 ... 2項目から3項目までの区間の値をそれぞれ1増やす

{ 1 , 4 , 6 , 7 , 9 }

↓ 2 3 5 ... 3項目から5項目までの区間の値をそれぞれ半分にする（小数点以下切り捨てる）

{ 1 , 4 , 3 , 3 , 4 }

↓ 0 1 5 ... 1項目から5項目までの区間の値の順序を反転する

{ 4 , 3 , 3 , 4 , 1 }

よって1項目の値は4である。

Solution in JAVA (judge verdict: Runtime Error)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.StringTokenizer;


public class Main {
	
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		
		final int N = sc.nextInt();
		final long a = sc.nextInt();
		final long d = sc.nextInt();
		
		final int M = sc.nextInt();
		int[] xs = new int[M];
		int[] ys = new int[M];
		int[] zs = new int[M];
		
		for(int i = 0; i < M; i++){
			xs[i] = sc.nextInt();
			ys[i] = sc.nextInt() - 1;
			zs[i] = sc.nextInt() - 1;
		}
		
		final int K = sc.nextInt() - 1;
		int[] query_K = new int[M + 1];
		query_K[M] = K;
		
		for(int i = M - 1; i >= 0; i--){
			if(xs[i] == 0 && ys[i] <= query_K[i + 1] && query_K[i + 1] <= zs[i]){
				query_K[i] = (zs[i] - query_K[K + 1]) + ys[i];
			}else{
				query_K[i] = query_K[i + 1];
			}
		}
		
		long answer = a + d * query_K[0];
		for(int i = 0; i < M; i++){
			if(xs[i] == 0){ continue; }
			else if(xs[i] == 1 && ys[i] <= query_K[i] && query_K[i] <= zs[i]){
				answer += 1;
			}else if(xs[i] == 2 && ys[i] <= query_K[i] && query_K[i] <= zs[i]){
				answer /= 2;
			}
		}
		
		System.out.println(answer);
	}	
	
	public static class Scanner {
		private BufferedReader br;
		private StringTokenizer tok;
		
		public Scanner(InputStream is){
			br = new BufferedReader(new InputStreamReader(is));
		}
		
		private void getLine(){
			try{
				while(!hasNext()){
					tok = new StringTokenizer(br.readLine());
				}
			} catch (IOException e){
				
			}
		}
		
		private boolean hasNext(){
			return tok != null && tok.hasMoreTokens();
		}
		
		public String next(){
			getLine(); return tok.nextToken();
		}
		
		public int nextInt(){
			return Integer.parseInt(next());
		}
	}
}