经典的线段树题目,也可以用块状链表做。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 using namespace std; 6 7 const int N = 200000; 8 const int M = 800; 9 int n, m, tot; 10 11 int max( int a, int b ) 12 { 13 return a > b ? a : b; 14 } 15 16 struct Block 17 { 18 int num[M]; 19 int size, maxn; 20 void init() 21 { 22 size = maxn = 0; 23 } 24 void push( int tmp ) 25 { 26 num[size++] = tmp; 27 if ( tmp > maxn ) maxn = tmp; 28 } 29 } bl[M]; 30 31 void update( int pos, int v ) 32 { 33 int cur = 0; 34 while ( pos > bl[cur].size ) 35 { 36 pos -= bl[cur].size; 37 cur++; 38 } 39 bl[cur].num[pos - 1] = v; 40 bl[cur].maxn = 0; 41 for ( int i = 0; i < bl[cur].size; i++ ) 42 { 43 bl[cur].maxn = max( bl[cur].maxn, bl[cur].num[i] ); 44 } 45 } 46 47 int query( int l, int r ) 48 { 49 int cur = 0, inc = r - l; 50 while ( l > bl[cur].size ) 51 { 52 l -= bl[cur].size; 53 cur++; 54 } 55 int ncur = cur; 56 r = l + inc; 57 while ( r > bl[ncur].size ) 58 { 59 r -= bl[ncur].size; 60 ncur++; 61 } 62 int ans = 0; 63 for ( int i = cur + 1; i <= ncur - 1; i++ ) 64 { 65 ans = max( ans, bl[i].maxn ); 66 } 67 if ( cur == ncur ) 68 { 69 for ( int j = l - 1; j < r; j++ ) 70 { 71 ans = max( ans, bl[cur].num[j] ); 72 } 73 } 74 else 75 { 76 for ( int j = l - 1; j < bl[cur].size; j++ ) 77 { 78 ans = max( ans, bl[cur].num[j] ); 79 } 80 for ( int j = 0; j < r; j++ ) 81 { 82 ans = max( ans, bl[ncur].num[j] ); 83 } 84 } 85 return ans; 86 } 87 88 int main() 89 { 90 while ( scanf("%d%d", &n, &m) != EOF ) 91 { 92 tot = 0; 93 bl[tot].init(); 94 int ps = sqrt((double)n); 95 for ( int i = 0; i < n; i++ ) 96 { 97 int tmp; 98 scanf("%d", &tmp); 99 if ( bl[tot].size == ps ) 100 { 101 tot++; 102 bl[tot].init(); 103 } 104 bl[tot].push(tmp); 105 } 106 char op[2]; 107 int a, b; 108 while ( m-- ) 109 { 110 scanf("%s%d%d", op, &a, &b); 111 if ( op[0] == 'Q' ) 112 { 113 printf("%d ", query( a, b )); 114 } 115 else 116 { 117 update( a, b ); 118 } 119 } 120 } 121 return 0; 122 }
对于这个题操作种类很少,可以写成二维数组的形式,看起来更简洁。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 using namespace std; 6 7 const int M = 550; 8 int b[M][M]; 9 int maxn[M]; 10 int n, q; 11 int ps; 12 13 int max( int a, int b ) 14 { 15 return a > b ? a : b; 16 } 17 18 void setv( int i, int j, int v ) 19 { 20 b[i][j] = v; 21 maxn[i] = max( maxn[i], b[i][j] ); 22 } 23 24 int query( int l, int r ) 25 { 26 int cur = l / ps, ncur = r / ps; 27 l = l % ps, r = r % ps; 28 int ret = -1; 29 for ( int i = cur + 1; i <= ncur - 1; i++ ) 30 { 31 ret = max( ret, maxn[i] ); 32 } 33 if ( cur != ncur ) 34 { 35 for ( int j = l; j < ps; j++ ) 36 { 37 ret = max( ret, b[cur][j] ); 38 } 39 for ( int j = 0; j <= r; j++ ) 40 { 41 ret = max( ret, b[ncur][j] ); 42 } 43 } 44 else 45 { 46 for ( int j = l; j <= r; j++ ) 47 { 48 ret = max( ret, b[cur][j] ); 49 } 50 } 51 return ret; 52 } 53 54 void update( int pos, int val ) 55 { 56 int i = pos / ps, j = pos % ps; 57 b[i][j] = val; 58 maxn[i] = -1; 59 for ( int k = 0; k < ps && i * ps + k < n; k++ ) 60 { 61 maxn[i] = max( maxn[i], b[i][k] ); 62 } 63 } 64 65 int main () 66 { 67 ps = 500; 68 while ( scanf("%d%d", &n, &q) != EOF ) 69 { 70 memset( maxn, -1, sizeof(maxn) ); 71 for ( int i = 0; i < n; i++ ) 72 { 73 int tmp; scanf("%d", &tmp); 74 setv( i / ps, i % ps, tmp ); 75 } 76 char op[2]; 77 int a, b; 78 while ( q-- ) 79 { 80 scanf("%s%d%d", op, &a, &b); 81 if ( op[0] == 'Q' ) 82 { 83 a--; b--; 84 printf("%d ", query( a, b )); 85 } 86 else 87 { 88 a--; 89 update( a, b ); 90 } 91 } 92 } 93 return 0; 94 }