HDU 1166 敌兵布阵 (单点更新,区间求和)
const int Max_N = 50100 ;int sum[Max_N<<2] , x[Max_N] ;void push_up(int root){ sum[root] = sum[root<<1] + sum[root<<1|1] ;}void make_tree(int L , int R , int root){ if(L == R){ sum[root] = x[L] ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ;}void update(int id , int c , int L , int R , int root){ if(L == R){ sum[root] += c ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , c , L , mid ,root<<1) ; else update(id , c , mid+1 , R , root<<1|1) ; push_up(root) ;}int query(int l , int r , int L , int R ,int root){ if(l <= L && R <= r) return sum[root] ; int mid = (L + R) >> 1 ; int ans = 0 ; if(l <= mid) ans += query(l , r , L , mid , root<<1) ; if(r > mid) ans += query(l , r , mid+1 , R , root<<1|1) ; return ans ;}int main(){ int T , n , i , a , b ; char str[8] ; cin>>T ; for(int cas = 1 ; cas <= T ; cas++){ printf("Case %d:\n",cas) ; scanf("%d",&n) ; for(i = 1 ; i <= n ; i++) scanf("%d",&x[i]) ; make_tree(1,n,1) ; while(scanf("%s",str) && strcmp(str,"End")!=0){ scanf("%d%d",&a,&b) ; if(str[0] == 'A') update(a , b , 1 , n , 1) ; else if(str[0] == 'S') update(a , -b , 1 , n , 1) ; else printf("%d\n",query(a , b , 1 , n , 1)) ; } } return 0 ;}
HDU 1394 Minimum Inversion Number (逆序对 , 单点更新,区间求和)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
const int Max_N = 5008 ;int Sum[Max_N<<1] ,x[Max_N];void push_up(int root){ Sum[root] = Sum[root<<1] + Sum[root<<1|1] ;}void make_tree(int L , int R , int root){ if(L == R){ Sum[root] = 0 ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ;}void update(int id , int L , int R , int root){ if(L == R){ Sum[root]++ ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , L , mid , root<<1) ; else update(id , mid+1 , R , root<<1|1) ; push_up(root) ;}int query(int l , int r , int L , int R , int root){ if(l <= L && R <= r) return Sum[root] ; int mid = (L + R) >> 1 ; int ans = 0 ; if(l <= mid) ans += query(l , r , L , mid , root<<1) ; if(r > mid) ans += query(l , r , mid+1 , R , root<<1|1) ; return ans ;}int main(){ int n , i , sum , ans ; while(cin>>n){ make_tree(1 , n , 1) ; //建一颗空树 sum = 0 ; for(i = 1 ; i <= n ; i++){ scanf("%d",&x[i]) ; x[i]++ ; // 序列变为[1,n] sum += query(x[i] , n , 1 , n , 1) ; // [x[i] , n]出现的个数之和 , 也就是在大于x[i],且位置在起左边的个数 update(x[i] , 1 , n , 1) ; //在x[i]位置插入1 } ans = sum ; // sum即为初始序列逆序数 for(i = 1 ; i < n ; i++){ // 将想x[i]移到尾巴。逆序数变化情况。 x[i]在头少了(x[i] -1 ) ,x[i] 在尾多了(n-x[i])个 ,总计多了: +(n-x[i])-(x[i]-1) sum = sum + n - x[i] - x[i] + 1 ; ans = min(ans ,sum) ; } printf("%d\n",ans) ; } return 0 ;}
HDU 1754 I Hate It (单点更新,区间最值)
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
const int Max_N = 200100 ;int Max[Max_N<<2] , x[Max_N] ;void push_up(int root){ Max[root] = max(Max[root<<1] , Max[root<<1|1]) ;}void make_tree(int L , int R , int root){ if(L == R){ Max[root] = x[L] ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ;}void update(int id , int c , int L , int R , int root){ if(L == R){ Max[root] = c ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , c , L , mid ,root<<1) ; else update(id , c , mid+1 , R ,root<<1|1) ; push_up(root) ;}int query(int l , int r , int L , int R , int root){ if(l <= L && R <= r) return Max[root] ; int mid = (L + R) >> 1 ; int ans = -1 ; if(l <= mid) ans = max(ans , query(l , r , L , mid , root<<1)) ; if(r > mid) ans = max(ans , query(l , r , mid+1 , R , root<<1|1)) ; return ans ;}int main(){ int n , m , i , a , b ; char str[2] ; while(cin>>n>>m){ for(i = 1 ; i <= n ; i++) scanf("%d",&x[i]) ; make_tree(1 , n , 1) ; while(m--){ scanf("%s%d%d",str,&a,&b) ; if(*str == 'U') update(a , b , 1 , n , 1) ; else printf("%d\n",query(a , b , 1 , n , 1)) ; } } return 0 ;}
There are n walruses standing in a queue in an airport. They are numbered starting from the queue's tail: the 1-st walrus stands at the end of the queue and the n-th walrus stands at the beginning of the queue. The i-th walrus has the age equal to ai.
The i-th walrus becomes displeased if there's a younger walrus standing in front of him, that is, if exists such j (i < j), that ai > aj. Thedispleasure of the i-th walrus is equal to the number of walruses between him and the furthest walrus ahead of him, which is younger than the i-th one. That is, the further that young walrus stands from him, the stronger the displeasure is.
The airport manager asked you to count for each of n walruses in the queue his displeasure.
The first line contains an integer n (2 ≤ n ≤ 105) — the number of walruses in the queue. The second line contains integers ai (1 ≤ ai ≤ 109).
Note that some walruses can have the same age but for the displeasure to emerge the walrus that is closer to the head of the queue needs to be strictly younger than the other one.
Print n numbers: if the i-th walrus is pleased with everything, print "-1" (without the quotes). Otherwise, print the i-th walrus's displeasure: the number of other walruses that stand between him and the furthest from him younger walrus.
6 10 8 5 3 50 45
2 1 0 -1 0 -1
7 10 4 6 3 2 8 15
4 2 1 0 -1 -1 -1
5 10 3 1 10 11
1 0 -1 -1 -1
题意:
有n个数的失望值,id失望值的定义是:id右边离它最远的且比它小的数 与 它本身之间 间隔的数的数量;
线段树,结点保存区间最小值 每次将当前的数更新为INF,然后查找整个区间内最右边的比它小的数的下标 .
const int Max_N = 100008 ;const int inf = 1000000800 ;int _Min[Max_N<<2] , x[Max_N] , ans[Max_N] ;void push_up(int root){ _Min[root] = min(_Min[root<<1] , _Min[root<<1|1]) ;}void make_tree(int L , int R , int root){ if(L == R){ _Min[root] = x[L] ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ;}void update(int id , int L , int R , int root){ if(L == R){ _Min[root] = inf ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , L , mid , root<<1) ; else update(id , mid+1 , R , root<<1|1) ; push_up(root) ;}//求区间[L,R]中 比C小 且 下标最大 的下标 。 其实二叉树遍历蛮重要的。 先右->后左。{好像不是3种遍历方式哦!}int query(int c , int L , int R , int root){ if(L == R) return L ; int mid = (L + R) >> 1 ; if(_Min[root<<1|1] < c) //右孩子的最小值比C小,则在右孩子中找 。 return query(c , mid+1 , R , root<<1|1) ; else return query(c , L , mid , root<<1) ;}int main(){ int n , i ; cin>>n ; for(i = 1 ; i <= n ; i++) scanf("%d" , &x[i]) ; make_tree(1 , n , 1) ; for(i = 1 ; i <= n ; i++){ update(i , 1 , n , 1) ; //将i处更新最大,更新完之后,_Min[1] = [1,n]最小值 if(_Min[1] < x[i]) ans[i] = query(x[i] , 1 , n , 1) - i - 1 ; // 为什么不能是query(x[i] , i , n , 1) ?因为[i,n]的节点编号不是1。注意这里 else ans[i] = -1 ; } printf("%d" , ans[1]) ; for(i = 2 ; i <= n ; i++) printf(" %d" , ans[i]) ; puts("") ; return 0 ;}
hdu 1698 (区间更新)
Just a Hook
typedef long long LL ;const int Max_N = 100008 ;int sum[Max_N<<2] ; /*和*/int color[Max_N<<2] ;/*颜色,-1表示不是纯色*//*向上更新,计算和*/void push_up(int root){ sum[root] = sum[root<<1] + sum[root<<1|1] ;}/*lazy操作,向下更新时,把纯色的颜色传递下去,同时更新和,若不是纯色则孩子节点的颜色之前已经更新*/void push_down(int root ,int L ,int R){ if(color[root] != -1){ color[root<<1] = color[root<<1|1] = color[root] ; color[root] = -1 ; /*向下更新就是因为root节点不再纯色*/ int mid = (L+R)>>1 ; sum[root<<1] = (mid-L+1) * color[root<<1] ; sum[root<<1|1] = (R-mid) * color[root<<1|1] ; }}/*建树*/void make_tree(int L , int R , int root){ color[root] = 1 ; if(L == R){ sum[root] = 1 ; return ; } int mid = (L+R)>>1 ; make_tree(L,mid,root<<1) ; make_tree(mid+1,R,root<<1|1) ; push_up(root) ;}/*更新区间[l,r]颜色为c*/void update(int l , int r , int c ,int L ,int R ,int root){ if(l <= L && R <= r){ color[root] = c ; sum[root] = (R-L+1) * c ; return ; } push_down(root,L,R) ; int mid = (L+R)>>1 ; if(l <= mid) update(l,r,c,L,mid,root<<1) ; if(r > mid) update(l,r,c,mid+1,R,root<<1|1) ; push_up(root) ;}int main(){ int T ,cas , n ,q , l ,r ,c; scanf("%d",&T) ; for(cas = 1 ; cas <= T ; cas++){ scanf("%d",&n) ; make_tree(1,n,1) ; scanf("%d",&q) ; while(q--){ scanf("%d%d%d",&l,&r,&c) ; update(l,r,c,1,n,1) ; } printf("Case %d: The total value of the hook is %d.\n",cas,sum[1]) ; } return 0 ;}
POJ 3468 (区间更新)
Time Limit: 5000MS | Memory Limit: 131072K | |
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.Each of the next Q lines represents an operation."C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000."Q a b" means querying the sum of Aa, Aa+1, ... , Ab.Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 4
Sample Output
455915
Hint
typedef long long LL ;const int Max_N = 101000 ;LL sum[Max_N<<2] , add[Max_N<<2] , x[Max_N];void push_up(int root){ sum[root] = sum[root<<1] + sum[root<<1|1] ;}void push_down(int L ,int R ,int root){ if(add[root]){ //纯色才向下更新。 add[root<<1] += add[root] ; add[root<<1|1] += add[root] ; int mid = (L + R)>>1 ; sum[root<<1] += add[root]*(mid-L+1) ; sum[root<<1|1] += add[root]*(R-mid) ; add[root] = 0 ; //更新完便不再是纯色了。 }}void make_tree(int L ,int R,int root){ add[root] = 0 ; if(L == R){ sum[root] = x[L] ; return ; } int mid = (L + R)>>1 ; make_tree(L,mid,root<<1) ; make_tree(mid+1,R,root<<1|1) ; push_up(root) ;}void update(int l ,int r ,LL c ,int L ,int R ,int root){ if(l <= L && R <= r){ add[root] += c ; sum[root] += c*(R-L+1) ; return ; } push_down(L,R,root) ; int mid = (L + R)>>1 ; if(l <= mid) update(l,r,c,L,mid,root<<1) ; if(r > mid) update(l,r,c,mid+1,R,root<<1|1) ; push_up(root) ;}LL query(int l ,int r ,int L ,int R ,int root){ if(l <= L && R <= r) return sum[root] ; push_down(L,R,root) ; // update中push_down的时候并没有把所有该更新的更新完。 int mid = (L + R)>>1 ; LL ans = 0 ; if(l <= mid) ans += query(l,r,L,mid,root<<1) ; if(r > mid) ans += query(l,r,mid+1,R,root<<1|1) ; return ans ;}int main(){ int i , n , q ,l,r; LL c; char str[2] ; cin>>n>>q ; for(i = 1 ; i <= n ; i++) scanf("%lld",&x[i]) ; make_tree(1,n,1) ; while(q--){ scanf("%s%d%d",str,&l,&r) ; if(str[0] == 'Q') printf("%lld\n",query(l,r,1,n,1)) ; else{ scanf("%lld",&c) ; update(l,r,c,1,n,1) ; } } return 0 ;}
HDU 4027 Can you answer these queries?(区间更新)
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
typedef long long LL ;const int Max_N = 100100 ;LL sum[Max_N<<2] , x[Max_N] ;int color[Max_N<<2] ;void push_up(int root){ sum[root] = sum[root<<1] + sum[root<<1|1] ; color[root] = color[root<<1] && color[root<<1|1] ;}void make_tree(int L , int R , int root){ if(L == R){ sum[root] = x[L] ; color[root] = sum[root] == 1 ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ;}void update(int l , int r , int L , int R , int root){ if(color[root]) return ; if(L == R){ sum[root] = LL (sqrt(sum[root])) ; color[root] = sum[root] == 1 ; return ; } int mid = (L + R) >> 1 ; if(l <= mid) update(l , r , L , mid , root<<1) ; if(r > mid) update(l , r , mid+1 , R , root<<1|1) ; push_up(root) ;}LL query(int l , int r , int L , int R , int root){ if(l <= L && R <= r) return sum[root] ; int mid = (L + R) >> 1 ; LL ans = 0 ; if(l <= mid) ans += query(l , r , L , mid , root<<1) ; if(r > mid) ans += query(l , r , mid+1 , R , root<<1|1) ; return ans ;}int main(){ int n , i , q , k = 1 , t , l , r; while(cin>>n){ printf("Case #%d:\n" , k++) ; for(i = 1 ; i <= n ; i++) scanf("%I64d",&x[i]) ; make_tree(1 , n , 1) ; scanf("%d",&q) ; while(q--){ scanf("%d%d%d",&t,&l,&r) ; if(l > r) swap(l , r) ; if(t) printf("%I64d\n",query(l , r , 1 , n , 1)) ; else update(l , r , 1 , n , 1) ; } puts("") ; } return 0 ;}
http://codeforces.com/problemset/problem/292/E (区间更新)
题目大意:两个数组,a和b,两种操作:
1:将数组a的区间[x,x+k-1]复制给数组b的区间[y,y+k-1]。
2:问当前b[x]的值。
const int Max_N = 100008 ;int Pos[Max_N<<2] ; //区间左端映射到数组A下标的起点void push_down(int root , int L , int R){ if(Pos[root]){ int mid = (L + R) >> 1 ; Pos[root<<1] = Pos[root] ; Pos[root<<1|1] = mid + 1 + Pos[root] - L ; Pos[root] = 0 ; }}void make_tree(int L , int R , int root){ Pos[root] = 0 ; if(L == R) return ; int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ;}void update(int l , int r , int start , int L , int R , int root){ if(l == L && R == r){ Pos[root] = start ; return ; } push_down(root , L , R) ; int mid = (L + R) >> 1 ; if(r <= mid) update(l , r , start , L , mid , root<<1) ; else if(l > mid) update(l , r , start , mid+1 , R , root<<1|1) ; else{ update(l , mid , start , L , mid , root<<1) ; update(mid+1 , r , start+mid+1-l , mid+1 , R ,root<<1|1) ; }}int query(int id , int L , int R , int root){ if(L == R) return Pos[root] ; push_down(root , L , R) ; int mid = (L + R) >> 1 ; if(id <= mid) return query(id , L , mid , root<<1) ; else return query(id , mid+1 , R , root<<1|1) ;}int A[Max_N] , B[Max_N] ;int main(){ int i ,t , n , m , x , y , k; cin>>n>>m ; for(i = 1 ; i <= n ; i++) scanf("%d" , &A[i]) ; for(i = 1 ; i <= n ; i++) scanf("%d" , &B[i]) ; make_tree(1 , n , 1) ; while(m--){ scanf("%d%d" , &t , &x) ; if(t == 1){ scanf("%d%d" , &y , &k) ; update(y , y+k-1 , x , 1 , n , 1) ; } else{ int id = query(x , 1 , n , 1) ; printf("%d\n" , id ? A[id] : B[x]) ; } } return 0 ;}
http://codeforces.com/problemset/problem/46/D (区间合并)
题目大意:
有一条长度为L的街道,有N个操作,操作有两种:(1)"1 a",表示有一辆长度为a的车开进来想找停车位;停车位必须满足与它前面的车距离至少为b,与后面的车距离至少为f;如果能找到这样的停车位;输出这辆车的起始位置(且这个位置最小),否则输出-1;(2)"2 a",表示第a个事件里进来停车的那辆车开出去了;算法思想:
建立起点为-b,终点为L+f的线段树;查找的时候,直接查找len+b+f的线段就可以了;注意这里存的是坐标点个数,而不是线段长度。
1 //节点个数 2 const int Max_N = 100300 ; 3 int L_canuse[Max_N<<2] , R_canuse[Max_N<<2] , All_canuse[Max_N<<2] , color[Max_N<<2] ; 4 5 void make_tree(int L , int R , int root){ 6 L_canuse[root] = R_canuse[root] = All_canuse[root] = R - L + 1 ; 7 color[root] = -1 ; 8 if(L == R) 9 return ;10 int mid = (L + R) >> 1 ;11 make_tree(L , mid , root<<1) ;12 make_tree(mid+1 , R , root<<1|1) ;13 }14 15 void push_up(int root , int L , int R){16 L_canuse[root] = L_canuse[root<<1] ;17 R_canuse[root] = R_canuse[root<<1|1] ;18 int mid = (L + R) >> 1 ;19 if(L_canuse[root] == mid - L + 1)20 L_canuse[root] += L_canuse[root<<1|1] ;21 if(R_canuse[root] == R - mid)22 R_canuse[root] += R_canuse[root<<1] ;23 All_canuse[root] = max(max(All_canuse[root<<1] , All_canuse[root<<1|1]),24 R_canuse[root<<1] + L_canuse[root<<1|1]) ;25 }26 27 void push_down(int root , int L , int R){28 if(color[root] != -1){29 color[root<<1] = color[root<<1|1] = color[root] ;30 int mid = (L + R) >> 1 ;31 L_canuse[root<<1] = R_canuse[root<<1] = All_canuse[root<<1] = (color[root]? mid - L + 1 : 0) ;32 L_canuse[root<<1|1] = R_canuse[root<<1|1] = All_canuse[root<<1|1] = (color[root]? R - mid : 0) ;33 color[root] = -1 ;34 }35 }36 37 void update(int l , int r , int c , int L , int R , int root){38 if(l <= L && R <= r){39 L_canuse[root] = R_canuse[root] = All_canuse[root] = (c? R - L + 1 : 0) ;40 color[root] = c ;41 return ;42 }43 push_down(root , L , R) ;44 int mid = (L + R) >> 1 ;45 if(l <= mid)46 update(l , r , c , L , mid , root<<1) ;47 if(r > mid)48 update(l , r , c , mid+1 , R , root<<1|1) ;49 push_up(root , L , R) ;50 }51 52 int query(int x , int L , int R , int root){53 if(L == R)54 return L ;55 push_down(root , L , R) ;56 int mid = (L + R) >> 1 ;57 if(x <= All_canuse[root<<1])58 return query(x , L , mid , root<<1) ;59 else if(x <= R_canuse[root<<1] + L_canuse[root<<1|1])60 return mid - R_canuse[root<<1] + 1 ;61 else62 return query(x , mid+1 , R , root<<1|1) ;63 }64 65 struct Car{66 int Start ;67 int Len ;68 }car[108];69 70 int main(){71 int n ,L , B , F , t , x ;72 cin>>L>>B>>F;73 make_tree(-B , L+F , 1) ;74 cin>>n ;75 for(int i = 1 ; i <= n ; i++){76 cin>>t>>x ;77 if(t == 1){78 car[i].Len = x ;79 if(All_canuse[1] < x + B + F + 1)80 puts("-1") ;81 else{82 car[i].Start = query(x+B+F , -B , L+F , 1) + B ;83 update(car[i].Start , car[i].Start + car[i].Len - 1, 0 , -B , L+F , 1) ;84 printf("%d\n",car[i].Start) ;85 }86 }87 else88 update(car[x].Start , car[x].Start + car[x].Len - 1 , 1 , -B , L+F , 1) ;89 }90 return 0 ;91 }
hdu 1504 (区间合并)
Tunnel Warfare
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3609 Accepted Submission(s): 1377
/*区间合并*/typedef long long LL ;const int Max_N = 50100 ; /*Left[i] ,到节点i左端点连续村庄的个数 ,Right[i] ,到节点i右端点连续村庄的个数 */int Left[Max_N<<2] , Right[Max_N<<2] ;void push_up(int L , int R , int root){ Left[root] = Left[root<<1] ; Right[root] = Right[root<<1|1] ; int mid = (L + R) >> 1 ; if(Left[root] == mid - L + 1) Left[root] += Left[root<<1|1] ; if(Right[root] == R - mid) Right[root] += Right[root<<1] ;}void make_tree(int L ,int R ,int root){ Left[root] = Right[root] = R - L + 1 ; if(L == R) return ; int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ;}void update(int id , int type , int L , int R , int root){ if(L == R){ Left[root] = Right[root] = type ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , type , L , mid , root<<1) ; else update(id , type , mid + 1 , R ,root<<1|1) ; push_up(L , R , root) ;}int query(int id , int L , int R , int root){ if(L == R) return Left[root] ; int mid = (L + R) >> 1 ; if(id <= mid){ if(Left[root<<1] == mid - L + 1) return Left[root<<1] + Left[root<<1|1] ; else if(L + Left[root<<1] > id) return Left[root<<1] ; else if(id > mid - Right[root<<1]) return Right[root<<1] + Left[root<<1|1] ; else return query(id , L , mid , root<<1) ; } else{ if(Right[root<<1|1] == R - mid) return Right[root<<1|1] + Right[root<<1] ; else if(id > R - Right[root<<1|1]) return Right[root<<1|1] ; else if(mid + 1 + Left[root<<1|1] > id) return Right[root<<1] + Left[root<<1|1] ; else return query(id , mid+1 , R , root<<1|1) ; }}int main(){ int n , m , id ; stack me ; char str[2] ; while(cin>>n>>m){ while(!me.empty()) me.pop() ; make_tree(1,n,1) ; while(m--){ scanf("%s" , str) ; if(str[0] == 'D'){ scanf("%d",&id) ; update(id , 0 , 1 , n , 1) ; me.push(id) ; } else if(str[0] == 'R'){ if(!me.empty()){ update(me.top() , 1 , 1 , n , 1) ; me.pop() ; } } else{ scanf("%d",&id) ; printf("%d\n",query(id,1,n,1)) ; } } } return 0 ;}