E - Tunnel Warfare (线段树求最长连续区间)
作者:互联网
题目链接:https://vjudge.net/contest/332656#problem/E
思路:
lmax 记录左边开始的最大连续区间, rmax 记录右边开始的最大连续区间 然后维护这两个值就可以了
主要是利用了线段树 (nod<<1) 、 ((nod<<1)+1) 所记录的区间是连续的特点
具体的解释还是看代码注释吧
1 #include <math.h> 2 #include <stdio.h> 3 #include <iostream> 4 #include <algorithm> 5 #include <string> 6 #include <string.h> 7 #include <vector> 8 #include <map> 9 #include <stack> 10 #include <random> 11 12 13 #define LL long long 14 15 const int maxn = 1e5 + 10; 16 17 18 19 struct segment_tree { 20 int l,r; 21 int lmax,rmax; 22 }tree[maxn<<2]; 23 24 25 void build(int l,int r,int nod) { 26 tree[nod].l = l; 27 tree[nod].r = r; 28 tree[nod].lmax = tree[nod].rmax = r - l + 1; 29 if (l == r) { 30 return ; 31 } 32 int mid = (l + r) >> 1; 33 build(l,mid,nod<<1); 34 build(mid+1,r,(nod<<1)+1); 35 } 36 37 void pushup(int k) { 38 tree[k].lmax = tree[k<<1].lmax; 39 if (tree[k<<1].lmax + tree[k<<1].l - 1 == tree[k<<1].r) { // 右临界点 == 区间的右端点 40 tree[k].lmax += tree[(k<<1)+1].lmax; 41 } 42 tree[k].rmax = tree[(k<<1)+1].rmax; 43 if (tree[(k<<1)+1].r - tree[(k<<1)+1].rmax + 1 == tree[(k<<1)+1].l) { // 左临界点 == 区间的左端点 44 tree[k].rmax += tree[k<<1].rmax; 45 } 46 } 47 48 49 void modify(int v,int x,int k=1) { 50 if (tree[k].l == tree[k].r ) { 51 tree[k].lmax = tree[k].rmax = v; 52 return ; 53 } 54 int mid = (tree[k].l + tree[k].r) >> 1; 55 if (x <= mid) { 56 modify(v,x,k<<1); 57 } else { 58 modify(v,x,(k<<1)+1); 59 } 60 pushup(k); 61 } 62 63 int query(int x,int k=1) { 64 if (tree[k].l == tree[k].r) { 65 return tree[k].lmax; 66 } 67 int mid = (tree[k].l + tree[k].r) >> 1; 68 if (x <= mid) { // 查询左子树 69 if (x >= tree[k<<1].r - tree[k<<1].rmax + 1) { // x >= 左临界点 70 return tree[k<<1].rmax + tree[(k<<1)+1].lmax; // 左边区间的rmax + 右边区间lmax 71 } else { 72 return query(x,k<<1); 73 } 74 } 75 else { // 查询右子树 76 if (x <= tree[(k<<1)+1].lmax + tree[(k<<1)+1].l - 1) { // x <= 右临界点 77 return tree[k<<1].rmax + tree[(k<<1)+1].lmax; // 左边区间的rmax + 右边区间的lmax 78 } else { 79 return query(x,(k<<1)+1); 80 } 81 } 82 } 83 84 int main() { 85 int n,m,x; 86 char s[2]; 87 while (~scanf("%d%d",&n,&m)) { 88 std::stack<int> sta; 89 build(1,n,1); 90 while (m--) { 91 scanf("%s",s); 92 if (s[0] == 'D') { 93 scanf("%d",&x); 94 modify(0,x); 95 sta.push(x); 96 } 97 else if (s[0] == 'R') { 98 x = sta.top(); 99 sta.pop(); 100 if (x > 0) 101 modify(1,x); 102 } 103 else { 104 scanf("%d",&x); 105 printf("%d\n",query(x)); 106 } 107 } 108 } 109 return 0; 110 }
标签:return,Warfare,Tunnel,scanf,tree,int,树求,include,sta 来源: https://www.cnblogs.com/-Ackerman/p/11643970.html