hdu1540(線段樹維護連續區間模型)
阿新 • • 發佈:2018-12-24
/* translation: 打地道戰,n個村莊用地道連成一條直線,鬼子有時破壞掉一個村莊,這時八路軍要修好這個據點。現在要求詢問任意一個村莊, 得出這個村莊現在與幾個村莊相連,包括它本身。 solution: 線段樹維護連續子區間 將村莊抽象成一個點,正常下值為1,被破壞後變成0,即可將題目抽象成一個求目標節點所在的最長連續1序列的區間的長度。 所以線上段樹裡面維護3個資訊,字首最長1序列,字尾最長1序列,以及最長1序列。具體維護的方法看程式碼。 note: *:習得線段樹維護連續子區間的正確姿勢ORZ date: 2016.11.19 */ #include <iostream> #include <cstdio> #include <stack> using namespace std; const int maxn = 50000 + 5; int n, q; int s[maxn*4], e[maxn*4]; int preLen[maxn*4], sufLen[maxn*4], maxLen[maxn*4]; void build(int o, int l, int r) { s[o] = l; e[o] = r; preLen[o] = sufLen[o] = maxLen[o] = r - l + 1; int m = (l + r) >> 1; if(l != r){ build(o << 1, l, m); build(o << 1 | 1, m+1, r); } } void pushUp(int o) { preLen[o] = preLen[o << 1]; sufLen[o] = sufLen[o << 1 | 1]; maxLen[o] = max(maxLen[o << 1], maxLen[o << 1 | 1]); maxLen[o] = max(maxLen[o], sufLen[o << 1] + preLen[o << 1 | 1]); if(preLen[o << 1] == e[o << 1] - s[o << 1] + 1) preLen[o] += preLen[o << 1 | 1]; if(sufLen[o << 1 | 1] == e[o << 1 | 1] - s[o << 1 | 1] + 1) sufLen[o] += sufLen[o << 1]; } void update(int o, int k, int v) { if(s[o] == k && e[o] == k){ preLen[o] = sufLen[o] = maxLen[o] = v; return; } if(s[o] == e[o]) return; int m = (s[o] + e[o]) >> 1; if(k <= m) update(o << 1, k, v); else update(o << 1 | 1, k, v); pushUp(o); } int query(int o, int k) { if(s[o] == e[o] || maxLen[o] == 0 || maxLen[o] == e[o] - s[o] + 1) return maxLen[o]; int m = (s[o] + e[o]) >> 1; int lc = o << 1, rc = o << 1 | 1; if(k <= m){ if(k >= e[lc] - sufLen[lc] + 1) return sufLen[lc] + preLen[rc]; else return query(lc, k); }else{ if(k <= s[rc] + preLen[rc] - 1) return preLen[rc] + sufLen[lc]; else return query(rc, k); } } int main() { //freopen("in.txt", "r", stdin); while(~scanf("%d%d", &n, &q)){ build(1, 1, n); char op; int a; stack<int> village; while(q--){ getchar(); scanf("%c", &op); if(op == 'D'){ scanf("%d", &a); village.push(a); //printf("push: %d\n", a); update(1, a, 0); } if(op == 'Q'){ scanf("%d", &a); printf("%d\n", query(1, a)); } if(op == 'R'){ if(!village.empty()){ a = village.top(); village.pop(); //printf("pop: %d\n", a); update(1, a, 1); } } } } return 0; }