(线段树区间合并)UVA 11235 - Frequent values

题意:

一个数列,多次查询L到R最多连续相同数字的数量。

分析:

显然区间合并。不过还就没写了,都有点忘了。

不过回忆一下,push_down还是写对了。

不过WA了,后来仔细想一想,光查询光用已经维护的答案还不够,还需要在query的时候再合并一下,才能更新出正确的答案。

 

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <vector>
 6 
 7 
 8 using namespace std;
 9 
10 const int inf = 0x3f3f3f3f;
11 const int maxn = 100010;
12 
13 struct Node {
14     int left, right;
15     int llen, rlen, zlen;
16     int lval, rval;
17 } node[maxn << 2];
18 
19 
20 
21 void push_up(int n) {
22     node[n].llen = node[n << 1].llen;
23     node[n].lval = node[n << 1].lval;
24     node[n].rlen = node[n << 1 | 1].rlen;
25     node[n].rval = node[n << 1 | 1].rval;
26     if(node[n << 1].llen == node[n << 1].right - node[n << 1].left + 1 && node[n << 1].rval == node[n << 1 | 1].lval) {
27         node[n].llen += node[n << 1 | 1].llen;
28     }
29     if(node[n << 1 | 1].rlen == node[n << 1 | 1].right - node[n << 1 | 1].left + 1 && node[n << 1].rval == node[n << 1 | 1].lval) {
30         node[n].rlen +=  node[n << 1].rlen;
31     }
32     node[n].zlen = max(node[n << 1].zlen, node[n << 1 | 1].zlen);
33     if(node[n << 1].rval == node[n << 1 | 1].lval) {
34         node[n].zlen = max(node[n].zlen, node[n << 1].rlen + node[n << 1 | 1].llen);
35     }
36 }
37 
38 void build(int n, int left, int right) {
39     node[n].left = left;
40     node[n].right = right;
41     if(left == right) {
42         scanf("%d", &node[n].lval);
43         node[n].rval = node[n].lval;
44         node[n].llen = node[n].rlen = node[n].zlen = 1;
45         return;
46     }
47     int mid = (left + right) >> 1;
48     build(n << 1, left, mid);
49     build(n << 1 | 1, mid + 1, right);
50     push_up(n);
51 }
52 
53 
54 int query(int n, int left, int right) {
55     if(node[n].left == left && node[n].right == right) {
56         return node[n].zlen;
57     }
58 //    printf("%d %d\n", node[n].left, node[n].right);
59     int mid = (node[n].left + node[n].right) >> 1;
60     int maxs = -1;
61     if(mid >= right)maxs = max(maxs, query(n << 1, left, right));
62     else if(mid < left)maxs = max(maxs, query(n << 1 | 1, left, right));
63     else {
64         int s = query(n << 1, left, mid);
65         int t = query(n << 1 | 1, mid + 1, right);
66         maxs = max(s, t);
67         int ls = min(node[n << 1].rlen, mid - left + 1);
68         int rs = min(node[n << 1 | 1].llen, right - mid);
69         if(node[n << 1].rval == node[n << 1 | 1].lval) {
70             maxs = max(maxs, ls + rs);
71         }
72     }
73 //    printf("--%d %d %d\n", node[n].left, node[n].right, maxs);
74     return maxs;
75 }
76 
77 int main() {
78 #ifndef ONLINE_JUDGE
79 //    freopen("1.in", "r", stdin);
80 //    freopen("1.out", "w", stdout);
81 #endif
82     int n, q;
83     while(~scanf("%d", &n) && n) {
84         scanf("%d", &q);
85         build(1, 1, n);
86 //        for(int i = 1; i <= 250; i++) {
87 //            printf("%d %d %d %d %d\n", node[i].left, node[i].right, node[i].llen, node[i].rlen, node[i].zlen);
88 //        }
89         while(q--) {
90             int l, r;
91             scanf("%d%d", &l, &r);
92             printf("%d\n", query(1, l, r));
93 //            puts("");
94         }
95     }
96     return 0;
97 
98 }

 

转载于:https://www.cnblogs.com/tak-fate/p/6965364.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值