首页 > 代码库 > (线段树区间合并)UVA 11235 - Frequent values

(线段树区间合并)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_JUDGE79 //    freopen("1.in", "r", stdin);80 //    freopen("1.out", "w", stdout);81 #endif82     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 }

 

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