这道题是要查询某个区间内数字出现的最大次数,序列不降,可以用线段树来做。
每个结点维护左右端点的值和出现次数(长度)以及该区间的Frequent values,然后向上合并即可。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 100001; 7 int a[N]; 8 9 struct Node 10 { 11 int l, r; 12 int len, llen, rlen; 13 friend Node operator + ( const Node & ln, const Node & rn ) 14 { 15 Node res; 16 res.l = ln.l; 17 res.r = rn.r; 18 if ( a[ln.l] == a[rn.l] ) 19 { 20 res.llen = ln.llen + rn.llen; 21 } 22 else 23 { 24 res.llen = ln.llen; 25 } 26 if ( a[ln.r] == a[rn.r] ) 27 { 28 res.rlen = ln.rlen + rn.rlen; 29 } 30 else 31 { 32 res.rlen = rn.rlen; 33 } 34 res.len = max( ln.len, rn.len ); 35 if ( a[ln.r] == a[rn.l] ) 36 { 37 res.len = max( res.len, ln.rlen + rn.llen ); 38 } 39 return res; 40 } 41 } node[N << 2]; 42 43 void build( int i, int l, int r ) 44 { 45 if ( l == r ) 46 { 47 node[i].l = node[i].r = l; 48 node[i].len = node[i].llen = node[i].rlen = 1; 49 return ; 50 } 51 int mid = ( l + r ) >> 1; 52 build( i << 1, l, mid ); 53 build( i << 1 | 1, mid + 1, r ); 54 node[i] = node[i << 1] + node[i << 1 | 1]; 55 } 56 57 Node query( int i, int l, int r ) 58 { 59 if ( node[i].l == l && node[i].r == r ) 60 { 61 return node[i]; 62 } 63 int mid = ( node[i].l + node[i].r ) >> 1; 64 if ( r <= mid ) 65 { 66 return query( i << 1, l, r ); 67 } 68 else if ( l > mid ) 69 { 70 return query( i << 1 | 1, l, r ); 71 } 72 else 73 { 74 return query( i << 1, l, mid ) + query( i << 1 | 1, mid + 1, r ); 75 } 76 } 77 78 int main () 79 { 80 int n, m; 81 while ( scanf("%d", &n), n ) 82 { 83 scanf("%d", &m); 84 for ( int i = 1; i <= n; i++ ) 85 { 86 scanf("%d", a + i); 87 } 88 build( 1, 1, n ); 89 while ( m-- ) 90 { 91 int a, b; 92 scanf("%d%d", &a, &b); 93 Node ans = query( 1, a, b ); 94 printf("%d ", ans.len); 95 } 96 } 97 return 0; 98 }