POJ 2892 线段树(连续问题)
2016-02-14 23:33
375 查看
题目
Tunnel WarfareTime Limit: 1000MS Memory Limit: 131072K
Total Submissions: 7496 Accepted: 3093
Description
During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.
Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
Input
The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event.
There are three different events described in different format shown below:
D x: The x-th village was destroyed.
Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.
R: The village destroyed last was rebuilt.
Output
Output the answer to each of the Army commanders’ request in order on a separate line.
Sample Input
7 9
D 3
D 6
D 5
Q 4
Q 5
R
Q 4
R
Q 4
Sample Output
1
0
2
4
题意
有几个村庄,D a表示a村庄被摧毁iu,R表示修复上一个村庄,Q a表示包含a的连续村庄有多少个,如果a被摧毁则输出0。题解
用线段树统计区间内有多少个连续的村长,为了方便表示,用T_L表示这个区间从最右端连续了多少个村庄,用T_R表示这个区间从最左端连续了多少个村庄。那么当一个区间的左儿子整个区间没有被摧毁村庄时,T[t].T_L = T[t<<1].T_L + T[t<<1|1].T_L。右儿子也是一样。那么我们就可以预先把该区间是满的个数算出来,直接判断是不是相等然后就可以合并了。最后查询的时候我们自顶向下寻找,但找到包含这个点的区间时返回。#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <set> #include <cmath> #include <stack> #include <map> #include <queue> #include <sstream> #include <vector> #define m0(a) memset(a,0,sizeof(a)) #define mm(a) memset(a,0x3f,sizeof(a)) #define m_1(a) memset(a,-1,sizeof(a)) #define f(i,a,b) for(i = a;i<=b;i++) #define fi(i,a,b) for(i = a;i>=b;i--) #define FFR freopen("data.in","r",stdin) #define FFW freopen("data.out","w",stdout) using namespace std; #define SIZE 50000 struct Po{ int T_L,T_R; }; Po T[SIZE*4+20]; int P[SIZE*4+20]; bool p1[SIZE*4+20]; bool p2[SIZE*4+20]; int NN; void aP(int a,int b){ int t = a+NN; T[t].T_L = T[t].T_R = b; for(t>>=1;t;t>>=1){ if(T[t<<1].T_L==P[t<<1]) T[t].T_L = T[t<<1].T_L + T[t<<1|1].T_L; else T[t].T_L = T[t<<1].T_L; if(T[t<<1|1].T_R==P[t<<1|1]) T[t].T_R = T[t<<1].T_R + T[t<<1|1].T_R; else T[t].T_R = T[t<<1|1].T_R; } } int init(int n){ NN = 1; int i = 0,j; m0(p1); m0(p2); p1[1] = 1; p2[1] = 1; while(NN<n){ NN<<=1; p1[NN] = 1; p2[NN-1] = 1; i++; } p2[NN*2-1] = 1; NN--; int k = i; int t = 1; f(i,0,k) f(j,1,1<<i){ T[t].T_R = T[t].T_L = 1<<(k-i); P[t++] = 1<<(k-i); } f(i,n+1,NN+1) aP(i,0); } int query(int a,int t,int l,int r){ if(l<=a&&a<=r){ if(a-l+1<=T[t].T_L){ if(!p1[t]) return T[t].T_L+T[t-1].T_R; else return T[t].T_L; } if(r-a+1<=T[t].T_R){ if(!p2[t]) return T[t].T_R+T[t+1].T_L; else return T[t].T_R; } } int m = (l+r)>>1; if(a<=m) query(a,t<<1,l,m); else query(a,t<<1|1,m+1,r); } int main() { ios_base::sync_with_stdio(false); cin.tie(0); int n,m; cin>>n>>m; init(n); char c; int a; int i; stack<int>st; f(i,1,m){ cin>>c; if(c=='D'){ cin>>a; aP(a,0); st.push(a); } if(c=='R'){ a = st.top();st.pop(); aP(a,1); } if(c=='Q'){ cin>>a; if(T[NN+a].T_L==0) cout<<"0"<<endl; else cout<<query(a,1,1,NN+1)<<endl; } } return 0; }
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- 用单调栈解决最大连续矩形面积问题
- 2632 Crashing Robots的解决方法
- 1573 Robot Motion (简单题)
- POJ 1200 Crazy Search(简单哈希)
- 【高手回避】poj3268,一道很水的dijkstra算法题