hdu 1540 Tunnel Warfare 线段树

给你一个01序列,每次将一个位置变成0或1。问某个位置所在的最长1串多长。

我们维护vec[k],k所代表序列中的最长子串长度,ls[k],k所代表序列中的最长前缀,rs[k],k所代表序列中的最长后缀。

合并很简单,vec[k] = max(vec[k << 1],vec[k << 1 | 1],rs[k <<1] + ls[k << 1 | 1]。ls[k] = ls[k << 1] (左半段不都是1) ls[k] = vec[k << 1] +  ls[k << 1 | 1](左半段都是1) rs维护同理。

然后考虑查询,最后查询位置所在的最长1串,必定是某个区间的rs和相邻区间的ls拼接起来的。

我们每次看,如果x属于左半段的最大后缀,那么这个最大后缀+右半段最大前缀就是答案。否则递归左子树去找。(x属于左半段)

如果x属于右半段的最大前缀,那么这个最大后缀+右半段最大前缀就是答案。否则递归右子树去找。(x属于右半段)

这题多case,题目没说.....

 1 #include <cstdio>
 2 #include <stack>
 3 using namespace std;
 4 stack <int> stk;
 5 int vec[210000],ls[210000],rs[210000];
 6 int n,q;
 7 void updata(int k,int l,int r)
 8 {
 9     int mid = l + r >> 1;
10     if (vec[k << 1] == mid - l + 1)
11         ls[k] = vec[k << 1] + ls[k << 1 | 1];
12     else
13         ls[k] = ls[k << 1];
14     if (vec[k << 1 | 1] == r - mid)
15         rs[k] = vec[k << 1 | 1] + rs[k << 1];
16     else
17         rs[k] = rs[k << 1 | 1];
18     vec[k] = max(rs[k << 1] + ls[k << 1 | 1],max(vec[k << 1],vec[k << 1 | 1]));
19 }
20 void build(int k,int l,int r)
21 {
22     if (l == r)
23     {
24         vec[k] = ls[k] = rs[k] = 1;
25         return;
26     }
27     int mid = l + r >> 1;
28     build(k << 1,l,mid);
29     build(k << 1 | 1,mid + 1,r);
30     updata(k,l,r);
31 }
32 void change(int k,int l,int r,int x,int vl)
33 {
34     if (l == r)
35     {
36         vec[k] = ls[k] = rs[k] = vl;
37         return;
38     }
39     int mid = l + r >> 1;
40     if (x <= mid) change(k << 1,l,mid,x,vl);
41     if (x >= mid + 1) change(k << 1 | 1,mid + 1,r,x,vl);
42     updata(k,l,r);
43 }
44 int query(int k,int l,int r,int x)
45 {
46     if (l == r)
47         return vec[k];
48     int mid = l + r >> 1;
49     if (x <= mid)
50     {
51         if (x >= (mid - rs[k << 1] + 1))
52             return rs[k << 1] + ls[k << 1 | 1];
53         else
54             return query(k << 1,l,mid,x);
55     }else
56     {
57         if (x <= (mid + ls[k << 1 | 1]))
58             return rs[k << 1] + ls[k << 1 | 1];
59         else
60             return query(k << 1 | 1,mid + 1,r,x);
61     }
62 }
63 int main()
64 {
65     while (scanf("%d%d",&n,&q) > 0)
66     {
67         build(1,1,n);
68         char str[10];
69         int tx;
70         for (int i = 1;i <= q;i++)
71         {
72             scanf("%s",str);
73             if (str[0] == 'D')
74             {
75                 scanf("%d",&tx);
76                 change(1,1,n,tx,0);
77                 stk.push(tx);
78             }else if (str[0] == 'Q')
79             {
80                 scanf("%d",&tx);
81                 printf("%d\n",query(1,1,n,tx));
82             }else
83             {
84                 change(1,1,n,stk.top(),1);
85                 stk.pop();
86             }
87         }
88     }
89     return 0;
90 }
posted @ 2020-01-13 21:43  IAT14  阅读(129)  评论(0编辑  收藏  举报