数据结构二之线段树Ⅰ——Count Color,Hotel,Transformation,Tree Generator™
普通的下標(biāo)線段樹
- Count Color
- Hotel
- Transformation
- Tree Generator?
Count Color
POJ2777
查詢區(qū)間內(nèi)顏色種類數(shù),觀察到顏色種類數(shù)只有30,完全可以狀壓成整型存儲(chǔ),沒有必要開30棵線段樹
區(qū)間內(nèi)有這顏色就置為111,沒有這個(gè)顏色就是000
非常簡單
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define maxn 100005 #define maxc 32 #define lson num << 1 #define rson num << 1 | 1 int n, T, m; struct node {int tag, ans; }t[maxn << 2];void pushdown( int num ) {if( ! t[num].tag ) return;t[lson].ans = t[lson].tag = t[num].tag;t[rson].ans = t[rson].tag = t[num].tag;t[num].tag = 0; }void modify( int num, int l, int r, int L, int R, int x ) {if( r < L or R < l ) return;if( L <= l and r <= R ) {t[num].ans = t[num].tag = 1 << x;return;}pushdown( num );int mid = ( l + r ) >> 1;modify( lson, l, mid, L, R, x );modify( rson, mid + 1, r, L, R, x );t[num].ans = t[lson].ans | t[rson].ans; }void build( int num, int l, int r ) {t[num].ans = 1 << 1, t[num].tag = 0;if( l == r ) return;int mid = ( l + r ) >> 1;build( lson, l, mid );build( rson, mid + 1, r ); }int query( int num, int l, int r, int L, int R ) {if( R < l or r < L ) return 0;if( L <= l and r <= R ) return t[num].ans;pushdown( num );int mid = ( l + r ) >> 1;return query( lson, l, mid, L, R ) | query( rson, mid + 1, r, L, R ); }int main() {scanf( "%d %d %d", &n, &T, &m );build( 1, 1, n );char opt[5]; int l, r, x;while( m -- ) {scanf( "%s %d %d", opt, &l, &r );if( l > r ) swap( l, r );if( opt[0] == 'C' ) {scanf( "%d", &x );modify( 1, 1, n, l, r, x );}else {int ans = query( 1, 1, n, l, r );printf( "%d\n", __builtin_popcount( ans ) ); }}return 0; }Hotel
POS3667
主要考察對(duì)于區(qū)間多個(gè)性質(zhì)的維護(hù)
維護(hù)最長連續(xù)空白區(qū)間,前綴最長,后綴最長,區(qū)間長度,以及區(qū)間下標(biāo)左右端點(diǎn)
主要考察代碼實(shí)現(xiàn)能力,思維量并不高
較簡單
#include <cstdio> #include <iostream> using namespace std; #define maxn 50005 #define lson num << 1 #define rson num << 1 | 1 struct node {int l, r, len, Max, lmax, rmax, tag; /* len 區(qū)間長度 Max 最長的連續(xù)空白區(qū)間 lmax 區(qū)間左端開始向右連續(xù)的空白區(qū)間長度 rmax 區(qū)間右端開始向左連續(xù)的空白區(qū)間長度 */ }t[maxn << 2]; int n, m;void build( int num, int l, int r ) {t[num].len = t[num].Max = t[num].lmax = t[num].rmax = r - l + 1;t[num].l = l, t[num].r = r, t[num].tag = 0;if( l == r ) return;int mid = l + r >> 1;build( lson, l, mid );build( rson, mid + 1, r ); }void pushup( int num ) {if( t[lson].lmax == t[lson].len ) t[num].lmax = t[lson].len + t[rson].lmax;else t[num].lmax = t[lson].lmax;if( t[rson].rmax == t[rson].len ) t[num].rmax = t[rson].len + t[lson].rmax;else t[num].rmax = t[rson].rmax;t[num].Max = max( t[lson].rmax + t[rson].lmax, max( t[lson].Max, t[rson].Max ) ); }void pushdown( int num ) {if( ! t[num].tag ) return;else if( ~ t[num].tag ) {t[lson].lmax = t[lson].rmax = t[lson].Max = 0;t[rson].lmax = t[rson].rmax = t[rson].Max = 0;}else {t[lson].lmax = t[lson].rmax = t[lson].Max = t[lson].len;t[rson].lmax = t[rson].rmax = t[rson].Max = t[rson].len;}t[lson].tag = t[rson].tag = t[num].tag;t[num].tag = 0; }void modify( int num, int l, int r, int L, int R, int k ) {if( R < l || r < L ) return;if( L <= l && r <= R ) {if( ~ k ) t[num].lmax = t[num].rmax = t[num].Max = 0;else t[num].lmax = t[num].rmax = t[num].Max = t[num].len;t[num].tag = k;return;}pushdown( num );int mid = ( l + r ) >> 1;modify( lson, l, mid, L, R, k );modify( rson, mid + 1, r, L, R, k );pushup( num ); }int query( int num, int l, int r, int k ) {pushdown( num );if( t[num].l == t[num].r ) return l;int mid = t[num].l + t[num].r >> 1;if( t[lson].Max >= k ) return query( lson, l, r, k );else if( t[rson].lmax + t[lson].rmax >= k ) return mid - t[lson].rmax + 1;else return query( rson, mid + 1, r, k ); }int main() {scanf( "%d %d", &n, &m );build( 1, 1, n );int opt, x, d, pos;while( m -- ) {scanf( "%d", &opt );if( opt & 1 ) {scanf( "%d", &d );if( t[1].Max < d ) printf( "0\n" );else {printf( "%d\n", pos = query( 1, 1, n, d ) );modify( 1, 1, n, pos, pos + d - 1, 1 );}}else {scanf( "%d %d", &x, &d );modify( 1, 1, n, x, x + d - 1, -1 );}}return 0; }Transformation
HDU4578
因?yàn)?span id="ozvdkddzhkzd" class="katex--inline">p∈[1,3]p\in [1,3]p∈[1,3],所以直接線段樹大暴力維護(hù)數(shù)不同次方的和
- tag : 賦值標(biāo)記
- add : 加標(biāo)記
- mul : 乘標(biāo)記
- sum1 : 區(qū)間內(nèi)數(shù)的一次方和
- sum2 : 區(qū)間內(nèi)數(shù)的二次方和
- sum3 : 區(qū)間內(nèi)數(shù)的三次方和
標(biāo)記內(nèi)有高低優(yōu)先順序,賦值第一,乘法第二,加法第三
(a+x)2=a2+x2+2ax(a+x)^2=a^2+x^2+2ax (a+x)2=a2+x2+2ax
(a1+x)2+(a2+x)2+...+(an+x)2=(a12+a22+...+an2)+2x(a1+a2+...+an)+nx2(a_1+x)^2+(a_2+x)^2+...+(a_n+x)^2=(a_1^2+a_2^2+...+a_n^2)+2x(a_1+a_2+...+a_n)+nx^2 (a1?+x)2+(a2?+x)2+...+(an?+x)2=(a12?+a22?+...+an2?)+2x(a1?+a2?+...+an?)+nx2
(a+x)3=a3+3a2x+3ax2+x3(a+x)^3=a^3+3a^2x+3ax^2+x^3 (a+x)3=a3+3a2x+3ax2+x3
(a1+x)3+...+(an+x)3=(a13+...+an3)+3x(a12+...+an2)+3x2(a1+...+an)+nx3(a_1+x)^3+...+(a_n+x)^3=(a_1^3+...+a_n^3)+3x(a_1^2+...+a_n^2)+3x^2(a_1+...+a_n)+nx^3 (a1?+x)3+...+(an?+x)3=(a13?+...+an3?)+3x(a12?+...+an2?)+3x2(a1?+...+an?)+nx3
通過公示可以看出,計(jì)算加法也有優(yōu)先順序,三次方第一,二次方第二,一次方第三
主要考察維護(hù)性質(zhì)標(biāo)記間的優(yōu)先順序,對(duì)代碼實(shí)現(xiàn)能力要求更高,思維含量不大,中檔
#include <cstdio> #define mod 10007 #define maxn 100005 #define int long long #define lson num << 1 #define rson num << 1 | 1 struct node {int l, r, sum1, sum2, sum3, add, mul, tag;void update1( int x ) {add = ( add + x ) % mod;sum3 = ( sum3 + 3 * x * sum2 + 3 * x * x * sum1 + ( r - l + 1 ) * x * x * x ) % mod;sum2 = ( sum2 + 2 * x * sum1 + ( r - l + 1 ) * x * x ) % mod;sum1 = ( sum1 + x * ( r - l + 1 ) ) % mod;}void update2( int x ) {add = add * x % mod;mul = mul * x % mod;sum3 = sum3 * x * x * x % mod;sum2 = sum2 * x * x % mod;sum1 = sum1 * x % mod;}void update3( int x ) {tag = x;mul = 1;add = 0;sum3 = x * x * x * ( r - l + 1 ) % mod;sum2 = x * x * ( r - l + 1 ) % mod;sum1 = x * ( r - l + 1 ) % mod;} }t[maxn << 2];node operator + ( node x, node y ) {node ans;ans.l = x.l, ans.r = y.r;ans.tag = ans.add = 0, ans.mul = 1;ans.sum1 = ( x.sum1 + y.sum1 ) % mod;ans.sum2 = ( x.sum2 + y.sum2 ) % mod;ans.sum3 = ( x.sum3 + y.sum3 ) % mod;return ans; }void build( int num, int l, int r ) {t[num].sum1 = t[num].sum2 = t[num].sum3 = 0;t[num].add = t[num].tag = 0, t[num].mul = 1;t[num].l = l, t[num].r = r;if( l == r ) return;int mid = l + r >> 1;build( lson, l, mid );build( rson, mid + 1, r ); }void pushdown( int num, int l, int r ) {if( t[num].tag ) {t[lson].update3( t[num].tag );t[rson].update3( t[num].tag );}if( t[num].mul ^ 1 ) {t[lson].update2( t[num].mul );t[rson].update2( t[num].mul );}if( t[num].add ) {t[lson].update1( t[num].add );t[rson].update1( t[num].add );}t[num].tag = t[num].add = 0, t[num].mul = 1; }void modify1( int num, int l, int r, int L, int R, int x ) {if( r < L || R < l ) return;if( L <= l && r <= R ) { t[num].update1( x ); return; }pushdown( num, l, r );int mid = l + r >> 1;modify1( lson, l, mid, L, R, x );modify1( rson, mid + 1, r, L, R, x );t[num] = t[lson] + t[rson]; }void modify2( int num, int l, int r, int L, int R, int x ) {if( r < L || R < l ) return;if( L <= l && r <= R ) { t[num].update2( x ); return; }pushdown( num, l, r );int mid = l + r >> 1;modify2( lson, l, mid, L, R, x );modify2( rson, mid + 1, r, L, R, x );t[num] = t[lson] + t[rson]; }void modify3( int num, int l, int r, int L, int R, int x ) {if( r < L || R < l ) return;if( L <= l && r <= R ) { t[num].update3( x ); return; }pushdown( num, l, r );int mid = l + r >> 1;modify3( lson, l, mid, L, R, x );modify3( rson, mid + 1, r, L, R, x );t[num] = t[lson] + t[rson]; }node query( int num, int l, int r, int L, int R ) {if( L <= l && r <= R ) return t[num];pushdown( num, l, r );int mid = l + r >> 1;if( R <= mid ) return query( lson, l, mid, L, R );else if( mid < L ) return query( rson, mid + 1, r, L, R );else return query( lson, l, mid, L, R ) + query( rson, mid + 1, r, L, R ); }signed main() {int n, m, opt, l, r, c;while( scanf( "%lld %lld", &n, &m ) and n and m ) {build( 1, 1, n );while( m -- ) {scanf( "%lld %lld %lld %lld", &opt, &l, &r, &c );switch ( opt ) {case 1 : { modify1( 1, 1, n, l, r, c ); break; }case 2 : { modify2( 1, 1, n, l, r, c ); break; }case 3 : { modify3( 1, 1, n, l, r, c ); break; }case 4 : { node ans = query( 1, 1, n, l, r );switch ( c ) {case 1 : { printf( "%lld\n", ans.sum1 ); break; }case 2 : { printf( "%lld\n", ans.sum2 ); break; }case 3 : { printf( "%lld\n", ans.sum3 ); break; }}break;}}}}return 0; }Tree Generator?
CF1149C
引理:樹上直徑為一段連續(xù)區(qū)間去掉匹配括號(hào)的最大長度
顯然,因?yàn)槠ヅ涞睦ㄌ?hào)在樹上就是對(duì)應(yīng)的影響再次回到原點(diǎn)
括號(hào)匹配是線段樹維護(hù)的一種模板,左括號(hào)為111,右括號(hào)為?1-1?1
顯然將匹配括號(hào)去掉后,區(qū)間形如))))((((可以只有(或))
考慮合并答案
假設(shè)這個(gè)區(qū)間的左子區(qū)間有右括號(hào)aaa個(gè),左括號(hào)bbb個(gè),右子區(qū)間有右括號(hào)c個(gè),左括號(hào)b個(gè)
那么這個(gè)區(qū)間合并的答案就是a+∣b?c∣+d=max(a+b?c+d,a?b+c+d)\rm a+|b-c|+d=max(a+b-c+d,a-b+c+d)a+∣b?c∣+d=max(a+b?c+d,a?b+c+d)
在形式上需要維護(hù)
- x=a+b\rm x=a+bx=a+b : 一個(gè)區(qū)間去掉匹配括號(hào)之后的后綴右括號(hào)加上后綴左括號(hào)的最大值
- y=a?b\rm y=a-by=a?b : 一個(gè)區(qū)間去掉匹配括號(hào)之后的后綴右括號(hào)減去后綴左括號(hào)的最大值
- z=?c+d\rm z=-c+dz=?c+d : 一個(gè)區(qū)間去掉匹配括號(hào)之后的前綴左括號(hào)減去前綴右括號(hào)的最大值
- w=c+d\rm w=c+dw=c+d : 一個(gè)區(qū)間去掉匹配括號(hào)之后的前綴左括號(hào)加上前綴右括號(hào)的最大值
前綴/后綴指從區(qū)間左端/右端開始的連續(xù)一段
由下往上兒子更新父親
-
考慮維護(hù)xxx
- 最優(yōu)劃分點(diǎn)在右邊
- 直接右兒子t[rson].x\rm t[rson].xt[rson].x更新
- 最優(yōu)劃分點(diǎn)在左邊
- 則一定包含右兒子區(qū)間,形如)))((
- 假設(shè)在左兒子的最佳劃分點(diǎn)后面有aaa個(gè)右括號(hào),bbb個(gè)左括號(hào)
- 右兒子剩下lll個(gè)左括號(hào),rrr個(gè)右括號(hào)
- 左右兒子括號(hào)匹配后
- x=a+∣b?r∣+l=max(a+b?r+l,a?b+r+l)\rm x=a+|b-r|+l=max(a+b-r+l,a-b+r+l)x=a+∣b?r∣+l=max(a+b?r+l,a?b+r+l)
- 同時(shí)a+b=t[lson].x;a?b=t[lson].y;l=t[rson].l;r=t[rson].r\rm a+b=t[lson].x;a-b=t[lson].y;l=t[rson].l;r=t[rson].ra+b=t[lson].x;a?b=t[lson].y;l=t[rson].l;r=t[rson].r
- 最優(yōu)劃分點(diǎn)在右邊
-
考慮維護(hù)yyy
-
最優(yōu)劃分點(diǎn)在右邊
- 直接右兒子t[rson].y\rm t[rson].yt[rson].y更新
-
最優(yōu)劃分點(diǎn)在左邊
- 則一定包含右兒子區(qū)間
- 假設(shè)在左兒子的最佳劃分點(diǎn)后面有aaa個(gè)右括號(hào),bbb個(gè)左括號(hào)
- 右兒子剩下lll個(gè)左括號(hào),rrr個(gè)右括號(hào)
- 左右兒子括號(hào)匹配后
- 1.1 b≥r\rm b\ge rb≥r : 右兒子不再有右括號(hào),左兒子剩b?r\rm b-rb?r個(gè)左括號(hào)y=a?l?(b?r)\rm y=a-l-(b-r)y=a?l?(b?r)
- 1.2 b<r\rm b<rb<r : 左兒子不再有左括號(hào),右兒子剩r?b\rm r-br?b個(gè)右括號(hào)y=(r?b)+a?l\rm y=(r-b)+a-ly=(r?b)+a?l
- 顯然一個(gè)加大于000的數(shù),一個(gè)減大于000的數(shù)
- max\rm maxmax選擇1.2更新,不用像xxx一樣分情況
- 同時(shí)a?b=t[lson].y;l=t[rson].l;r=t[rson].r;y=r(?b+a)?l=r?l+t[lson].y\rm a-b=t[lson].y;l=t[rson].l;r=t[rson].r;y=r(-b+a)-l=r-l+t[lson].ya?b=t[lson].y;l=t[rson].l;r=t[rson].r;y=r(?b+a)?l=r?l+t[lson].y
-
-
考慮zzz
-
最優(yōu)劃分點(diǎn)在左邊
- 直接左兒子t[lson].z\rm t[lson].zt[lson].z更新
-
最優(yōu)劃分點(diǎn)在右邊
-
則一定包含左兒子區(qū)間
-
假設(shè)在右兒子的最佳劃分點(diǎn)前面有ccc個(gè)右括號(hào),ddd個(gè)左括號(hào)
-
左兒子剩下lll個(gè)左括號(hào)rrr個(gè)右括號(hào)
-
左右兒子括號(hào)匹配
-
1.1 l≥c\rm l\ge cl≥c 右兒子不再有右括號(hào),左兒子剩l?c\rm l-cl?c個(gè)左括號(hào),y=d+(l?c)?r\rm y=d+(l-c)-ry=d+(l?c)?r
-
1.2 l<c\rm l<cl<c 左兒子不再有左括號(hào),右兒子剩c?l\rm c-lc?l個(gè)右括號(hào),y=d?(c?l)?r\rm y=d-(c-l)-ry=d?(c?l)?r
-
-
顯然一個(gè)加大于000的數(shù),一個(gè)減大于000的數(shù)
-
max\rm maxmax選擇1.1更新
-
同時(shí)?c+d=t[rson].zl=t[lson].lr=t[lson].rz=d+l?c?r=(?c+d)+l?r\rm -c+d=t[rson].z l=t[lson].l r=t[lson].rz=d+l-c-r=(-c+d)+l-r?c+d=t[rson].zl=t[lson].lr=t[lson].rz=d+l?c?r=(?c+d)+l?r
-
-
-
考慮kkk
- 最優(yōu)劃分點(diǎn)在左邊
- 直接左兒子t[lson].w\rm t[lson].wt[lson].w更新
- 最優(yōu)劃分點(diǎn)在右邊
- 則一定包含左兒子區(qū)間
- 假設(shè)在右兒子的最佳劃分點(diǎn)前面有ccc個(gè)右括號(hào),ddd個(gè)左括號(hào)
- 左兒子剩下lll個(gè)左括號(hào),rrr個(gè)右括號(hào)
- 左右兒子括號(hào)匹配后
- x=d+∣l?c∣+r=max(d+l?c+r,d+c?l+r)\rm x=d+|l-c|+r=max(d+l-c+r,d+c-l+r)x=d+∣l?c∣+r=max(d+l?c+r,d+c?l+r)
- 同時(shí)?c+d=t[rson].zc+d=t[rson].wl=t[lson].lr=t[lson].r\rm -c+d=t[rson].z c+d=t[rson].w l=t[lson].l r=t[lson].r?c+d=t[rson].zc+d=t[rson].wl=t[lson].lr=t[lson].r
- 最優(yōu)劃分點(diǎn)在左邊
困難
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define maxn 300005 #define lson num << 1 #define rson num << 1 | 1 struct node {//全是取最大值//全是區(qū)間內(nèi)去掉匹配括號(hào)后 形如)))))(( int x; //后綴左括號(hào)加后綴右括號(hào) int y; //后綴右括號(hào)減后綴左括號(hào) int z; //前綴左括號(hào)減前綴右括號(hào) int w; //前綴左括號(hào)加前綴右括號(hào) int l; //區(qū)間內(nèi)未匹配左括號(hào)數(shù)量 int r; //區(qū)間內(nèi)未匹配有括號(hào)數(shù)量 int ans;//區(qū)間內(nèi)的最長直徑答案 //前綴/后綴指從區(qū)間左端/右端開始的連續(xù)一段s[i] }t[maxn << 2]; int n, m; char s[maxn];void pushup( int num ) {//左右兒子區(qū)間會(huì)有左兒子的左括號(hào)和右兒子的有括號(hào)匹配情況 if( t[lson].l > t[rson].r ) {t[num].l = t[lson].l - t[rson].r + t[rson].l;t[num].r = t[lson].r;}else {t[num].l = t[rson].l;t[num].r = t[lson].r + t[rson].r - t[lson].l;}/*后綴左括號(hào)加后綴右括號(hào) 1.最優(yōu)劃分點(diǎn)在右邊 直接右兒子t[rson].x更新 2.最優(yōu)劃分點(diǎn)在左邊 則一定包含右兒子區(qū)間 形如)))(( 假設(shè)在左邊兒子的最佳劃分點(diǎn)后面有a個(gè)右括號(hào)b個(gè)左括號(hào) 右邊兒子剩下l個(gè)左括號(hào)r個(gè)右括號(hào) 左右兒子括號(hào)匹配后x=a+|b-r|+l=max(a+b-r+l,a-b+r+l)同時(shí)已知有 a+b=t[lson].x a-b=t[lson].y l=t[rson].l r=t[rson].r*/t[num].x = max( t[rson].x, max( t[lson].x - t[rson].r + t[rson].l, t[lson].y + t[rson].r + t[rson].l ) );/*后綴右括號(hào)減后綴左括號(hào)1.最優(yōu)劃分點(diǎn)在右邊 直接右兒子t[rson].y更新 2.最優(yōu)劃分點(diǎn)在左邊 則一定包含右兒子區(qū)間假設(shè)在左邊兒子的最佳劃分點(diǎn)后面有a個(gè)右括號(hào)b個(gè)左括號(hào) 右邊兒子剩下l個(gè)左括號(hào)r個(gè)右括號(hào) 左右兒子括號(hào)匹配1.1 b>=r 右兒子不再有右括號(hào) 左兒子剩b-r個(gè)左括號(hào) y=a-l-(b-r)1.2 b<r 左兒子不再有左括號(hào) 右兒子剩r-b個(gè)右括號(hào) y=(r-b)+a-l顯然一個(gè)加大于0的數(shù) 一個(gè)減大于0的數(shù)max選擇1.2更新 不用像x一樣分情況 同時(shí)已知有 a-b=t[lson].y l=t[rson].l r=t[rson].ry=r(-b+a)-l=r-l+t[lson].y*/t[num].y = max( t[rson].y, t[lson].y + t[rson].r - t[rson].l );/*前綴左括號(hào)減前綴右括號(hào) 1.最優(yōu)劃分點(diǎn)在左邊 直接左兒子t[lson].z更新 2.最優(yōu)劃分點(diǎn)在右邊 則一定包含左兒子區(qū)間假設(shè)在右邊兒子的最佳劃分點(diǎn)前面有c個(gè)右括號(hào)d個(gè)左括號(hào) 左邊兒子剩下l個(gè)左括號(hào)r個(gè)右括號(hào) 左右兒子括號(hào)匹配1.1 l>=c 右兒子不再有右括號(hào) 左兒子剩l-c個(gè)左括號(hào) y=d+(l-c)-r1.2 l<c 左兒子不再有左括號(hào) 右兒子剩c-l個(gè)右括號(hào) y=d-(c-l)-r顯然一個(gè)加大于0的數(shù) 一個(gè)減大于0的數(shù)max選擇1.1更新 同時(shí)已知有-c+d=t[rson].z l=t[lson].l r=t[lson].rz=d+l-c-r=(-c+d)+l-r*/t[num].z = max( t[lson].z, t[rson].z + t[lson].l - t[lson].r );/*前綴左括號(hào)加前綴右括號(hào)1.最優(yōu)劃分點(diǎn)在左邊 直接左兒子t[lson].w更新 2.最優(yōu)劃分點(diǎn)在右邊 則一定包含左兒子區(qū)間 假設(shè)在右兒子的最佳劃分點(diǎn)前面有c個(gè)右括號(hào)d個(gè)左括號(hào) 左兒子剩下l個(gè)左括號(hào)r個(gè)右括號(hào) 左右兒子括號(hào)匹配后x=d+|l-c|+r=max(d+l-c+r,d+c-l+r)同時(shí)已知有 -c+d=t[rson].z c+d=t[rson].w l=t[lson].l r=t[lson].r*/t[num].w = max( t[lson].w, max( t[lson].l + t[lson].r + t[rson].z, t[lson].r - t[lson].l + t[rson].w ) );/*合并答案 1.就是左兒子或右兒子的答案2.假設(shè)這個(gè)區(qū)間的左子區(qū)間有右括號(hào)a個(gè)左括號(hào)b個(gè) 右子區(qū)間有右括號(hào)c個(gè)左括號(hào)b個(gè)那么這個(gè)區(qū)間從中間合并的答案就是a+|b-c|+d=max(a+b-c+d,a-b+c+d)同時(shí)已知有a+b=t[lson].x a-b=t[lson].y -c+d=t[rson].z c+d=t[rson]w */t[num].ans = max( max( t[lson].ans, t[rson].ans ), max( t[lson].x + t[rson].z, t[lson].y + t[rson].w ) ); }void modify( int num, int k ) {t[num].x = 1;t[num].y = max( -k, 0 );t[num].z = max( k, 0 );t[num].l = k == 1;t[num].r = k == -1;t[num].w = 1;t[num].ans = 1; }void build( int num, int l, int r ) {if( l == r ) { modify( num, s[l] == '(' ? 1 : -1 ); return; }int mid = l + r >> 1;build( lson, l, mid );build( rson, mid + 1, r );pushup( num ); }void modify( int num, int l, int r, int pos, int k ) {if( l == r ) { modify( num, k ); return; }int mid = l + r >> 1;if( pos <= mid ) modify( lson, l, mid, pos, k );else modify( rson, mid + 1, r, pos, k );pushup( num ); }int main() {scanf( "%d %d %s", &n, &m, s + 1 );n = strlen( s + 1 );build( 1, 1, n );printf( "%d\n", t[1].ans );while( m -- ) {int x, y;scanf( "%d %d", &x, &y );modify( 1, 1, n, x, s[y] == '(' ? 1 : -1 );modify( 1, 1, n, y, s[x] == '(' ? 1 : -1 );swap( s[x], s[y] );printf( "%d\n", t[1].ans );}return 0; }總結(jié)
以上是生活随笔為你收集整理的数据结构二之线段树Ⅰ——Count Color,Hotel,Transformation,Tree Generator™的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 觉悟第四关怎么过 觉悟第四关介绍
- 下一篇: 数据结构二之线段树Ⅱ——KiKi‘s K