1. 程式人生 > >Tunnel Warfare HDU - 1540(線段樹最長連續區間)

Tunnel Warfare HDU - 1540(線段樹最長連續區間)

ont div n) pan Go build lse ons #define

題意:

一條線上的點,D x是破壞這個點,Q x是表示查詢以x所在的最長的連續的點的個數,R是恢復上一次破壞的點。 解析: 線段樹結點 設置一個 lq記錄區間左端點開始的最大連續個數, rq 記錄區間右端點開始的最大的連續個數 其它和原來一樣即可 看代碼吧。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define
mem(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 1000010, INF = 0x7fffffff; typedef long long LL; int a, b, x, y, ans; struct node{ int l, r, w, lq, rq; }Node[maxn]; void build(int k, int ll, int rr) { Node[k].l = ll, Node[k].r = rr; if(Node[k].l == Node[k].r) { Node[k].lq
= Node[k].rq = Node[k].w = 1; return; } int m = (ll + rr) / 2; build(k*2, ll, m); build(k*2+1, m+1, rr); Node[k].lq = Node[k].rq = Node[k].w = Node[k*2].w + Node[k*2+1].w; } void chp(int k) //單點修改 { if(Node[k].l == Node[k].r) { Node[k].lq = Node[k].rq = Node[k].w = y;
return; } int m = (Node[k].l + Node[k].r) / 2; if(x <= m) chp(k*2); else chp(k*2+1); Node[k].w = Node[k*2].w + Node[k*2+1].w; Node[k].lq = Node[k*2].lq; //修改後初始化 父結點的最長連續左區間 為 左子結點的最長連續左區間 Node[k].rq = Node[k*2+1].rq; //父結點的最長連續右區間 為 右子結點的最長連續右區間 if(Node[k*2].lq == Node[k*2].r - Node[k*2].l + 1) //如果左子結點的最長連續左區間 為整個區間的長度 那麽父結點的最長連續左區間 應該 加上 右子結點的最長連續右區間 Node[k].lq += Node[k*2+1].lq; if(Node[k*2+1].rq == Node[k*2+1].r - Node[k*2+1].l + 1) // 同理 Node[k].rq += Node[k*2].rq; } void qinter(int k, int t) { if(Node[k].l == Node[k].r || Node[k].w == 0 || Node[k].w == Node[k].r - Node[k].l + 1) //如果當前區間為單點、區間和為0、區間和為區間長度 那麽就沒必要往下搜了 返回即可 { ans += Node[k].w; return; } int m = (Node[k].l + Node[k].r) / 2; if(t <= m) //如果t在左子樹 { if(t >= Node[k*2].r - Node[k*2].rq + 1) //如果t大於左子樹右區間的左端點 說明t在左子樹的右區間內 { ans += (Node[k*2].rq + Node[k*2+1].lq); //然後用左子樹的最長連右區間 + 右子樹的最長連續左區間 return; } else qinter(k*2, t); //如果不在右區間 則向下搜 } else //同理 { if(t <= Node[k*2+1].l + Node[k*2+1].lq - 1) { ans += (Node[k*2+1].lq + Node[k*2].rq); return; } else qinter(k*2+1, t); } } int main() { int n, m; ans = 0; while(~scanf("%d%d",&n,&m)){ build(1, 1, n); stack<int> G; getchar(); for(int i=0; i<m; i++) { char str[1010]; scanf("%s",str); if(strcmp(str, "D") == 0) { scanf("%d",&x); G.push(x); y = 0; chp(1); } else if(strcmp(str, "R") == 0) { x = G.top(); G.pop(); y = 1; chp(1); } else if(strcmp(str, "Q") == 0) { scanf("%d",&x); ans = 0; qinter(1, x); printf("%d\n",ans); } } } return 0; }

Tunnel Warfare HDU - 1540(線段樹最長連續區間)