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 }

猜你喜欢

转载自www.cnblogs.com/-Ackerman/p/11643970.html