Tunnel Warfare HDU - 1540(线段树最长连续区间)
Posted wtsruvf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tunnel Warfare HDU - 1540(线段树最长连续区间)相关的知识,希望对你有一定的参考价值。
题意:
一条线上的点,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 ",ans); } } } return 0; }
以上是关于Tunnel Warfare HDU - 1540(线段树最长连续区间)的主要内容,如果未能解决你的问题,请参考以下文章
HDU1540 Tunnel Warfare —— 线段树 区间合并
hdu1540 Tunnel Warfare 线段树/树状数组