探险

探险

(explore.pas/c/cpp)

【题目描述】

    小林和亮亮来到森林中探险,森林中有一条长度为 S 的小路(编号从 1 到 S),且在小路上时常会起雾,亮亮也可以用神光让雾消散。

小林则关心在某一位置的视野。若位置 x 有浓雾,则位置 x 的视野为 0。若从 x 一直到 S 或从 x 一直到 1 全都没有浓雾,则视野为 INF。其他情况下,位置x 的 视 野 定 义 为 max{ L-R +1 }, 其 中 L, R 满 足 : L ≤ x ≤ R ,"x∈{A∈N|L≤A≤R},格子没有浓雾 。

具体来说,会有以下事件发生:

1、“1 L R”小路的[L, R]部分产生了浓雾;

2、“2 L R”小路的[L, R]部分浓雾散去了。

3、“3 X” 查询 X 点的视野。

一开始,小路上没有任何浓雾。

【输入格式】

第一行一个整数,为小路的长度 S。

第二行一个整数,为事件数 Q。

接下来 Q 行,每行一个事件,格式如题目描述。

【输出格式】

对于每一个询问事件,输出一个整数或一行字符串“INF”,代表所求视野。

【样例输入】

5

5

1 2 4

3 1

3 4

2 3 3

3 3

【样例输出】

INF

0

1

【数据规模】

对于 40%的数据, S*Q <= 5*10^7。

对于 100%的数据, 2≤S≤100,000,2≤Q≤200,000, 1≤L≤R≤S, 1≤X≤S。

【问题分析】

    线段树,这一题需要用到lazy_tag,就是标记法打线段树。

    线段树每个结点记录两个值lzy和now(0或1表示是否有浓雾),1表示当前结点能够有浓雾,一个结点没有浓雾当且仅当他的左孩子和右孩子都没有浓雾。

    Lzy用来记录改变值,就是当前结点要变成什么样的状态,用到这个结点时把now变为lzy,并且更新孩子时要把lzy下放,下放之后当前节点lzy变为-1,表示当前节点没有lzy,没有lzy就不下放,孩子还是原来的值。Lzy最大的作用就是节省更新的时间,不必要每个点的去更新,当然也有很多线段树的题不需要用lzy。

  1 #include<cstdio>
  2 #include<iostream>
  3 using namespace std;
  4 const int N = 200009;
  5 struct Node
  6 {
  7     int lzy, now;
  8 }t[4*N];
  9 int n, m;
 10 void pushdown(int rt, int lc, int rc)
 11 {
 12     if(t[rt].lzy == -1) return;
 13     t[lc].lzy = t[rt].lzy;
 14     t[lc].now = t[lc].lzy;
 15     t[rc].lzy = t[rt].lzy;
 16     t[rc].now = t[rc].lzy;
 17     t[rt].lzy = -1;
 18     return;
 19 }
 20 void update(int l, int r, int rt, int L, int R, int tag)
 21 {
 22     if(l > r || r < L || l > R) return;
 23     if(L <= l && r <= R)
 24     {
 25         t[rt].now = tag;
 26         t[rt].lzy = tag;
 27         return;
 28     }
 29     int mid = (l + r) >> 1;
 30     int lc = rt << 1;
 31     int rc = rt << 1 | 1;
 32     pushdown(rt, lc, rc);
 33     update(l, mid, lc, L, R, tag);
 34     update(mid+1, r, rc, L, R, tag);
 35     t[rt].now = (t[lc].now | t[rc].now);
 36 }
 37 int query(int l, int r, int rt, int L, int R)
 38 {
 39     if(l > r || r < L || l > R) return 0;
 40     if(L <= l && r <= R) return t[rt].now;
 41     int mid = (l + r) >> 1;
 42     int lc = rt << 1;
 43     int rc = rt << 1 | 1;
 44     pushdown(rt, lc, rc);
 45     int ltag = query(l, mid, lc, L, R);
 46     int rtag = query(mid+1, r, rc, L, R);
 47     t[rt].now = (t[lc].now | t[rc].now);
 48     if(R <= mid) return ltag;
 49     if(mid < L) return rtag;
 50     return (ltag | rtag);
 51 }
 52 int main()
 53 {
 54     freopen("explore.in", "r", stdin);
 55     freopen("explore.out", "w", stdout);
 56     scanf("%d%d", &n, &m);
 57     for(int i = 1; i <= m; i++)
 58     {
 59         int v;
 60         scanf("%d", &v);
 61         if(v == 1)
 62         {
 63             int l, r;
 64             scanf("%d%d", &l, &r);
 65             update(1, n, 1, l, r, 1);
 66         }
 67         if(v == 2)
 68         {
 69             int l, r;
 70             scanf("%d%d", &l, &r);
 71             update(1, n, 1, l, r, 0);
 72         }
 73         if(v == 3)
 74         {
 75             int x;
 76             scanf("%d", &x);
 77             int xtag = query(1, n, 1, x, x);
 78             if(xtag)
 79             {
 80                 puts("0");
 81                 continue;
 82             }
 83             int ltag = query(1, n, 1, 1, x);
 84             if(!ltag)
 85             {
 86                 puts("INF");
 87                 continue;
 88             }
 89             int rtag = query(1, n, 1, x, n);
 90             if(!rtag)
 91             {
 92                 puts("INF");
 93                 continue;
 94             }
 95             int l = 1, r = x, Ll = x, Rl = x;
 96             while(l <= r)
 97             {
 98                 int mid = (l + r) >> 1;
 99                 int vtag = query(1, n, 1, mid, x);
100                 if(!vtag)
101                     Ll = mid, r = mid - 1;
102                 else l = mid + 1;
103             }
104             l = x; r = n;
105             while(l <= r)
106             {
107                 int mid = (l + r) >> 1;
108                 int vtag = query(1, n, 1, x, mid);
109                 if(!vtag)
110                     Rl = mid, l = mid + 1;
111                 else r = mid - 1;
112             }
113             printf("%d\n", Rl - Ll + 1);
114         }
115     }
116     return 0;
117 }
View Code

 

posted @ 2020-03-12 21:28  Johnny-English  阅读(257)  评论(0编辑  收藏  举报