线段树区间合并--连续区间问题

// hdu 1540 数据很奇葩。用讨论区里面的话形容这题很合适--"九九八十一难,这道题比北大的数据真是坑出翔来了"

// poj 2892 原题 一摸一样

//题意: 给定n个村庄排成一行,它们相邻的村庄通过地道相连,有三种操作 1- 炸毁第x个村庄 2-修复上一个被炸毁的村庄 3- 询问(输出)第x个村庄还能和几个村庄通过地道相连(自己也算一个)

// 划重点。。。输入要求到eof题目没说,而且scanf ()==2不行 得用~scanf()  cin不知道  没试。村庄被炸毁了如果再来炸一波,必须得再入栈,修复的时候得先修它。(被炸毁了还来炸得多大仇)

// 思路  维护最大连续区间。其实也可以维护最值。另外一种写法 就是用set存被销毁的村庄(0和n+1也要存),然后询问x的时候 求a=*low_bound (x)  b=*(low_bound(x)--),如果a==x结果为0 不然为a-b-1     orz👁

参考博客:  点我! 好文 看了代码就能 懂

 // 板子题 我好菜 菜哭了
1
#include<cstdio> 2 #include<algorithm> 3 #define L k<<1 4 #define R k<<1|1 5 #define mid (tree[k].l+tree[k].r)>>1 6 using namespace std; 7 8 const int MAXN = 50000+5; 9 10 int n, m; 11 struct sgmemt_tree { 12 int l, r; 13 int ll, rl;// 此区间最左边得连续区间长度 和 最右边的连续区间的长度 14 int ml;// 此区间最大连续区间长度 15 } tree[4*MAXN+1]; 16 17 inline void build(int k, int l, int r) { 18 tree[k].l = l; tree[k].r = r; 19 tree[k].ll = tree[k].rl = tree[k].ml = r - l + 1; 20 if(l == r) return; 21 int m = (l + r) / 2; 22 build(L, l, m); 23 build(R, m+1, r); 24 } 25 26 inline void update(int k, int x, int cnt) { 27 if(tree[k].l == tree[k].r) { 28 tree[k].ll = tree[k].rl = tree[k].ml = cnt; 29 return ; 30 } 31 int m = mid; 32 if(x <= m) update(L, x, cnt); 33 else update(R, x, cnt); 34 // ml 35 tree[k].ml = max(tree[L].ml, tree[R].ml); 36 tree[k].ml = max(tree[k].ml, tree[L].rl + tree[R].ll); 37 // ll 38 tree[k].ll = tree[L].ll == tree[L].r-tree[L].l+1 ? tree[L].ll+tree[R].ll : tree[L].ll; 39 // r; 40 tree[k].rl = tree[R].rl == tree[R].r-tree[R].l+1 ? tree[R].rl+tree[L].rl : tree[R].rl; 41 } 42 43 inline int query(int k, int x) { 44 if(tree[k].l==tree[k].r || tree[k].ml==0 || tree[k].r-tree[k].l+1==tree[k].ml) return tree[k].ml; 45 int m = mid; 46 if(x <= m) { 47 if(x >= m-tree[L].rl+1) return query(L, x) + query(R, m+1); 48 else return query(L, x); 49 } 50 else { 51 if(x <= m+tree[R].ll) return query(L, m) + query(R, x); 52 return query(R, x); 53 } 54 } 55 56 int main() { 57 char com[10]; 58 int x; 59 int stack[MAXN], destroy[MAXN], top; 60 while(~scanf("%d%d", &n, &m)) { 61 top = 0; 62 build(1, 1, n); 63 for(int i = 0; i != m; ++i) { 64 scanf("%s", com); 65 if(com[0] == 'D') { 66 scanf("%d", &x); 67 update(1, x, 0); 68 stack[top++] = x; 69 } 70 else if(com[0] == 'R' && top) { 71 update(1, stack[--top], 1); 72 } 73 else { 74 scanf("%d", &x); 75 printf("%d\n", query(1, x)); 76 } 77 } 78 } 79 return 0; 80 }

 

posted @ 2019-10-08 02:48  pupil337  阅读(242)  评论(0编辑  收藏  举报