【地狱副本】数据结构之线段树Ⅲ——区间最值/赋值/修改/历史值操作(HDU5306,Tyvj 1518,【清华集训2015】V,HDU6315,HDU1828,POJ3162)
文章目錄
- Gorgeous Sequence
- Tyvj 1518 CPU監(jiān)控
- 【清華集訓(xùn)2015】V
- Naive Operations
- Picture
- Walking Race
Gorgeous Sequence
HDU5306
操作
- 區(qū)間與xxx取min\rm minmin
- 查詢區(qū)間最大值
- 查詢區(qū)間和
比較暴力的線段樹維護(hù)區(qū)間
- Max : 區(qū)間最大值
- sub_max : 嚴(yán)格小于最大值的區(qū)間次大值
- cnt_max : 最大值個(gè)數(shù)
- sum : 區(qū)間和
- tag : 區(qū)間取min\rm minmin的標(biāo)記記錄值
考慮取min\rm minmin操作走到一個(gè)區(qū)間上
-
最大值都不大于取min\rm minmin的對(duì)象,說明操作沒用,return
-
如果小于最大值卻嚴(yán)格大于次大值
此時(shí)的操作相當(dāng)于區(qū)間加,打標(biāo)記 sum-=(Max-x)*max_cnt;Max=x
-
否則暴力走兩邊
利用勢(shì)能分析時(shí)間復(fù)雜度
- 定義勢(shì)能函數(shù)為∑idi\sum_i d_i∑i?di?,iii是線段樹上的節(jié)點(diǎn),did_idi?是這個(gè)節(jié)點(diǎn)對(duì)應(yīng)的區(qū)間中,互不相同的元素個(gè)數(shù)
- 初始時(shí),顯然勢(shì)能是O(nlogn)O(\rm nlogn)O(nlogn)
- 暴力對(duì)長(zhǎng)度為nnn的區(qū)間做min\rm minmin,消耗的時(shí)間是O(n)O(n)O(n),勢(shì)能也會(huì)減少O(n)O(n)O(n)
Tyvj 1518 CPU監(jiān)控
BZOJ3064
操作
- 區(qū)間加
- 區(qū)間賦值
- 查詢區(qū)間最大值
- 查詢區(qū)間歷史最大值
線段樹維護(hù)
- Max : 區(qū)間最大值
- Hmax : 區(qū)間歷史最大值
- add : 區(qū)間加標(biāo)記
- Hadd : 區(qū)間歷史最大加標(biāo)記
- tag : 區(qū)間賦值標(biāo)記
- Htag : 區(qū)間歷史最大賦值標(biāo)記
假想不合并標(biāo)記,每個(gè)節(jié)點(diǎn)上有一個(gè)隊(duì)列(按照時(shí)間先進(jìn)先出),放著所有曾經(jīng)推過來的標(biāo)記
下推標(biāo)記時(shí),將該節(jié)點(diǎn)上所有的標(biāo)記推到兩個(gè)兒子處,并清空隊(duì)列
對(duì)于每個(gè)節(jié)點(diǎn),每次有一個(gè)區(qū)間加add標(biāo)記推來時(shí),令Max←Max+add 然后Hmax←max(Hmax,Max)
設(shè)推來的加法標(biāo)記分別為add[1...k]add[1...k]add[1...k],其前綴和為S[1...k]S[1...k]S[1...k]
則打上第iii個(gè)標(biāo)記之后,Max的值為Max+S[i]
所以,Hmax的值為max?i=1kMax+S[i]=Max+max?i=1kS[i]\max_{i=1}^k Max+S[i]=Max+\max_{i=1}^k S[i]maxi=1k?Max+S[i]=Max+maxi=1k?S[i]
因此只需記錄max?i=1kS[i]\max_{i=1}^k S[i]maxi=1k?S[i],就能得知該標(biāo)記隊(duì)列對(duì)節(jié)點(diǎn)的影響
合并加法標(biāo)記時(shí)簡(jiǎn)單求和,前iii個(gè)標(biāo)記合并后恰好等于S[i]S[i]S[i],那么max?i=1kS[i]\max_{i=1}^k S[i]maxi=1k?S[i]可以表述為標(biāo)記的歷史最大值Hadd
此題含有賦值操作,賦值操作優(yōu)先級(jí)更高,做法略有不同
賦值一次相當(dāng)于前面所有的加標(biāo)記和當(dāng)前最大值都會(huì)被改變
所以賦值的時(shí)候,先下放所有的加標(biāo)記,然后清空(包括歷史)
同時(shí),在加標(biāo)記的時(shí)候如果已經(jīng)有了賦值標(biāo)記,直接把加標(biāo)記疊加在賦值標(biāo)記上
同時(shí)記錄賦值歷史的最大值,其很有可能成為歷史最大值
#include <cstdio> #include <iostream> using namespace std; #define inf 1e18 #define maxn 100005 #define int long long #define lson num << 1 #define rson num << 1 | 1 struct node {int Max, Hmax, add, Hadd, tag, Htag; }t[maxn << 2]; int a[maxn];void build( int num, int l, int r ) {t[num].Max = t[num].Hmax = t[num].tag = t[num].Htag = -inf;t[num].add = t[num].Hadd = 0;if( l == r ) { t[num].Max = t[num].Hmax = a[l]; return; }int mid = ( l + r ) >> 1;build( lson, l, mid );build( rson, mid + 1, r );t[num].Max = t[num].Hmax = max( t[lson].Max, t[rson].Max ); }void pushup( int num ) {t[num].Max = max( t[lson].Max, t[rson].Max );t[num].Hmax = max( t[lson].Hmax, t[rson].Hmax ); }void down( int num, int add, int Hadd ) {if( t[num].Htag != -inf )t[num].Htag = max( t[num].Htag, t[num].tag + Hadd ), t[num].tag += add;elset[num].Hadd = max( t[num].Hadd, t[num].add + Hadd ), t[num].add += add; }void pushdown( int num, int l, int r ) {if( t[num].tag == -inf and ! t[num].add ) return;t[num].Hmax = max( t[num].Hmax, max( t[num].Htag, t[num].Max + t[num].Hadd ) );if( t[num].add ) {t[num].Max += t[num].add;if( l ^ r ) {down( lson, t[num].add, t[num].Hadd );down( rson, t[num].add, t[num].Hadd ); } }if( t[num].tag != -inf ) {t[num].Max = t[num].tag;if( l ^ r ) {t[lson].tag = t[rson].tag = t[num].tag;t[lson].Htag = max( t[lson].Htag, t[num].Htag );t[rson].Htag = max( t[rson].Htag, t[num].Htag );}}t[num].add = t[num].Hadd = 0;t[num].tag = t[num].Htag = -inf; }void add( int num, int l, int r, int L, int R, int val ) {pushdown( num, l, r );if( R < l or r < L ) return;if( L <= l and r <= R ) {if( t[num].tag != -inf ) t[num].tag += val, t[num].Htag = max( t[num].Htag, t[num].tag );else t[num].add += val, t[num].Hadd = max( t[num].Hadd, t[num].add );pushdown( num, l, r );return;}pushdown( num, l, r );int mid = ( l + r ) >> 1;add( lson, l, mid, L, R, val );add( rson, mid + 1, r, L, R, val );pushup( num ); }void modify( int num, int l, int r, int L, int R, int val ) {pushdown( num, l, r );if( R < l or r < L ) return;if( L <= l and r <= R ) {t[num].tag = val;t[num].Htag = max( t[num].Htag, val );pushdown( num, l, r );return;}pushdown( num, l, r );int mid = ( l + r ) >> 1;modify( lson, l, mid, L, R, val );modify( rson, mid + 1, r, L, R, val );pushup( num ); }int query_max( int num, int l, int r, int L, int R ) {if( R < l or r < L ) return -inf;pushdown( num, l, r );if( L <= l and r <= R ) return t[num].Max;int mid = ( l + r ) >> 1;return max( query_max( lson, l, mid, L, R ), query_max( rson, mid + 1, r, L, R ) ); }int queryHmax( int num, int l, int r, int L, int R ) {if( R < l or r < L ) return -inf;pushdown( num, l, r );if( L <= l and r <= R ) return t[num].Hmax;int mid = ( l + r ) >> 1;return max( queryHmax( lson, l, mid, L, R ), queryHmax( rson, mid + 1, r, L, R ) ); }signed main() {int n, m, l, r, x; char opt[5];scanf( "%lld", &n );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] );build( 1, 1, n );scanf( "%lld", &m );while( m -- ) {scanf( "%s %lld %lld", opt, &l, &r );switch ( opt[0] ) {case 'Q' : { printf( "%lld\n", query_max( 1, 1, n, l, r ) ); break; }case 'A' : { printf( "%lld\n", queryHmax( 1, 1, n, l, r ) ); break; }case 'P' : { scanf( "%lld", &x ); add( 1, 1, n, l, r, x ); break; }case 'C' : { scanf( "%lld", &x ); modify( 1, 1, n, l, r, x );break; }}}return 0; }【清華集訓(xùn)2015】V
UOJ164
整那么高大上的物理電阻屁用沒有
操作
- 區(qū)間加
- 區(qū)間減
- 區(qū)間賦值
- 查詢單點(diǎn)值
- 查詢單點(diǎn)歷史最大值
這題很巧的轉(zhuǎn)化將多個(gè)操作合并成了一種形式
將標(biāo)記改寫成(a,b)形式,標(biāo)記對(duì)值的貢獻(xiàn)轉(zhuǎn)移形式改寫成x←max(x+a,b)
- 區(qū)間加:(val,-inf)
- 區(qū)間減:(-val,-inf)
- 區(qū)間賦值:(-inf,val)
標(biāo)記的合并可以推出來,因?yàn)榧臃▽?duì)取最大值滿足分配率
- 假設(shè)原來的標(biāo)記為(a1,b1),新來標(biāo)記為(a2,b2)
- max?(x+a1,b1)←(a2,b2)?max?(max?(x+a1,b1)+a2,b2)?max?(max?(x+a1+a2,b1+a2),b2)\max(x+a_1,b_1)\leftarrow (a_2,b_2)\Rightarrow \max\Big(\max(x+a_1,b_1)+a_2,b_2\Big)\Rightarrow \max\Big(\max(x+a_1+a_2,b_1+a_2),b_2\Big)max(x+a1?,b1?)←(a2?,b2?)?max(max(x+a1?,b1?)+a2?,b2?)?max(max(x+a1?+a2?,b1?+a2?),b2?)
- 新來標(biāo)記合并最后即為x←max?(x+a1+a2,max?(a2+b1,b2))x\leftarrow \max\Big(x+a_1+a_2,\max(a_2+b_1,b_2)\Big)x←max(x+a1?+a2?,max(a2?+b1?,b2?))
考慮當(dāng)前最大值的更新
兩個(gè)標(biāo)記取max\rm maxmax相當(dāng)于兩個(gè)分段一次函數(shù)取max\rm maxmax
max((a1,b1),(a2,b2))=(max(a1,a2),max(b1,b2))\rm max\Big((a_1,b_1),(a_2,b_2))=(max(a_1,a_2),max(b_1,b_2)\Big)max((a1?,b1?),(a2?,b2?))=(max(a1?,a2?),max(b1?,b2?))
再考慮歷史最大值的更新
(a0,b0)表示當(dāng)前,(a1,b1)表示歷史最大值,(c0,d0)表示傳遞點(diǎn)當(dāng)前,(c1,d1)表示傳遞點(diǎn)歷史最大
合并(a0,b0)和(c0,d0):(a0+c0,max?(b0+c0,d0))\Big(a_0+c_0,\max(b_0+c_0,d_0)\Big)(a0?+c0?,max(b0?+c0?,d0?))
合并(a1,b1)和(c1,d1),先把(c1,d1)作用在(a0,b0)上,(a0+c1,max?(b0+c1,d1))\Big(a_0+c_1,\max(b_0+c_1,d_1)\Big)(a0?+c1?,max(b0?+c1?,d1?))
再和(a1,b1)取max:(max?(a1,a0+c1),max?(b1,b0+c1,d1))\Big(\max(a_1,a_0+c_1),\max(b_1,b_0+c_1,d_1)\Big)(max(a1?,a0?+c1?),max(b1?,b0?+c1?,d1?))
(a,b相當(dāng)于兒子,c,d代表父親的信息)
#include <cstdio> #include <iostream> using namespace std; #define maxn 500005 #define int long long #define lson num << 1 #define rson num << 1 | 1 struct node {int a, b, maxa, maxb; }t[maxn << 2]; int w[maxn]; const int inf = 1e18;void build( int num, int l, int r ) {t[num].a = t[num].maxa = 0;t[num].b = t[num].maxb = -inf;if( l == r ) return;int mid = l + r >> 1;build( lson, l, mid );build( rson, mid + 1, r ); }void pushdown( int num ) {if( ! t[num].a and t[num].b == -inf ) return;t[lson].maxa = max( t[lson].maxa, t[lson].a + t[num].maxa );t[lson].maxb = max( t[lson].maxb, max( t[lson].b + t[num].maxa, t[num].maxb ) );t[rson].maxa = max( t[rson].maxa, t[rson].a + t[num].maxa );t[rson].maxb = max( t[rson].maxb, max( t[rson].b + t[num].maxa, t[num].maxb ) );t[lson].a = max( t[lson].a + t[num].a, -inf );t[lson].b = max( t[lson].b + t[num].a, t[num].b );t[rson].a = max( t[rson].a + t[num].a, -inf );t[rson].b = max( t[rson].b + t[num].a, t[num].b );t[num].a = t[num].maxa = 0;t[num].b = t[num].maxb = -inf; }void modify( int num, int l, int r, int L, int R, int a, int b ) {if( r < L or R < l ) return;if( L <= l and r <= R ) {t[num].a = max( t[num].a + a, -inf );t[num].b = max( t[num].b + a, b );t[num].maxa = max( t[num].a, t[num].maxa );t[num].maxb = max( t[num].b, t[num].maxb );return;}pushdown( num );int mid = l + r >> 1;modify( lson, l, mid, L, R, a, b );modify( rson, mid + 1, r, L, R, a, b ); }int query( int num, int l, int r, int pos, int k ) {if( l == r ) {if( ! k ) return max( w[l] + t[num].a, t[num].b );else return max( w[l] + t[num].maxa, t[num].maxb );}pushdown( num );int mid = l + r >> 1;if( pos <= mid ) return query( lson, l, mid, pos, k );else return query( rson, mid + 1, r, pos, k ); }signed main() {int n, m;scanf( "%lld %lld", &n, &m );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &w[i] );build( 1, 1, n );for( int i = 1, opt, l, r, x;i <= m;i ++ ) {scanf( "%lld", &opt );switch ( opt ) {case 1 : { scanf( "%lld %lld %lld", &l, &r, &x ), modify( 1, 1, n, l, r, x, 0 ); break; }case 2 : { scanf( "%lld %lld %lld", &l, &r, &x ), modify( 1, 1, n, l, r, -x, 0 ); break; }case 3 : { scanf( "%lld %lld %lld", &l, &r, &x ), modify( 1, 1, n, l, r, -inf, x ); break; }case 4 : { scanf( "%lld", &x ), printf( "%lld\n", query( 1, 1, n, x, 0 ) ); break; }case 5 : { scanf( "%lld", &x ), printf( "%lld\n", query( 1, 1, n, x, 1 ) ); break; }}}return 0; }Naive Operations
HDU6315
剛開始區(qū)間全為000,每次區(qū)間只+1+1+1
記錄區(qū)間的最小值,
當(dāng)最小值為000的時(shí)候,說明多疊加了一個(gè)bib_ibi?的倍數(shù)
答案增加111,然后重新把最小值置位bib_ibi? (這倆操作要走到葉子節(jié)點(diǎn)后再實(shí)行)
否則就打上整體?1-1?1的標(biāo)記
#include <cstdio> #include <iostream> using namespace std; #define maxn 100005 #define int long long #define lson num << 1 #define rson num << 1 | 1 struct node {int sum, tag, Min; }t[maxn << 2]; int b[maxn];void build( int num, int l, int r ) {t[num].tag = t[num].sum = 0;if( l == r ) { t[num].Min = b[l]; return; }int mid = l + r >> 1;build( lson, l, mid );build( rson, mid + 1, r );t[num].Min = min( t[lson].Min, t[rson].Min ); }void pushdown( int num ) {if( ! t[num].tag ) return;t[lson].tag += t[num].tag;t[rson].tag += t[num].tag;t[lson].Min -= t[num].tag;t[rson].Min -= t[num].tag;t[num].tag = 0; }void modify( int num, int l, int r, int L, int R ) {if( R < l or r < L ) return;if( L <= l and r <= R ) {t[num].Min --;if( t[num].Min ) { t[num].tag ++; return; }else if( l == r ) { t[num].sum ++, t[num].Min = b[l]; return; }}pushdown( num );int mid = l + r >> 1;modify( lson, l, mid, L, R );modify( rson, mid + 1, r, L, R );t[num].sum = t[lson].sum + t[rson].sum;t[num].Min = min( t[lson].Min, t[rson].Min ); }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].sum;pushdown( num );int mid = l + r >> 1;return query( lson, l, mid, L, R ) + query( rson, mid + 1, r, L, R ); }signed main() {int n, Q, l, r; char opt[10];while( ~ scanf( "%lld %lld", &n, &Q ) ) {for( int i = 1;i <= n;i ++ ) scanf( "%lld", &b[i] );build( 1, 1, n );for( int i = 1;i <= Q;i ++ ) {scanf( "%s %d %d", opt, &l, &r );if( opt[0] == 'a' ) modify( 1, 1, n, l, r );else printf( "%lld\n", query( 1, 1, n, l, r ) );}}return 0; }Picture
HDU1828
掃描線求矩陣周長(zhǎng)模板題
從下往上掃描線掃,橫線長(zhǎng)度:現(xiàn)在這次總區(qū)間被覆蓋的長(zhǎng)度和上一次總區(qū)間被覆蓋的長(zhǎng)度之差的絕對(duì)值
而豎線長(zhǎng)度為,區(qū)間的段數(shù)*2,乘以222是因?yàn)橐欢螀^(qū)間左右各一條
e.g. 段數(shù)cntcntcnt的計(jì)算
- 若區(qū)間[0,10]被[1,2][4,5]覆蓋,則cnt=2
- 若區(qū)間[0,10]被[1,3][4,5]覆蓋,則cnt=1(兩區(qū)間剛好連在一起)
- 若區(qū)間[0,10]被[1,5][2,6]覆蓋,則cnt=1(兩區(qū)間連起來還是一段)
掃描線中的線段樹的一個(gè)節(jié)點(diǎn)代表一個(gè)單位長(zhǎng)度線段
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; #define maxn 200005 #define lson num << 1 #define rson num << 1 | 1 struct node {int l, r, h, op;node(){}node( int L, int R, int H, int Op ) {l = L, r = R, h = H, op = Op;} }E[maxn]; struct tree {int l, r, len, cnt, tag, flag_l, flag_r; }t[maxn << 2];bool cmp( node x, node y ) { return x.h < y.h; }void build( int num, int l, int r ) {t[num].l = l, t[num].r = r;t[num].len = t[num].cnt = t[num].tag = t[num].flag_l = t[num].flag_r = 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[num].tag ) {t[num].len = t[num].r - t[num].l + 1;t[num].cnt = t[num].flag_l = t[num].flag_r = 1;}else if( t[num].l == t[num].r )t[num].len = t[num].cnt = t[num].flag_l = t[num].flag_r = 0;else {t[num].len = t[lson].len + t[rson].len;t[num].cnt = t[lson].cnt + t[rson].cnt - ( t[lson].flag_r and t[rson].flag_l );t[num].flag_l = t[lson].flag_l, t[num].flag_r = t[rson].flag_r;} }void modify( int num, int l, int r, int val ) {if( t[num].r < l or r < t[num].l ) return;if( l <= t[num].l and t[num].r <= r ) {t[num].tag += val;pushup( num );return;}modify( lson, l, r, val );modify( rson, l, r, val );pushup( num ); }int Fabs( int x ) { return x < 0 ? -x : x; }int main() {int n, x1, y1, x2, y2;while( ~ scanf( "%d", &n ) ) {int L = 1e9, R = -1e9;for( int i = 1;i <= n;i ++ ) {scanf( "%d %d %d %d", &x1, &y1, &x2, &y2 );E[i] = node( x1, x2, y1, 1 );E[i + n] = node( x1, x2, y2, -1 );L = min( L, x1 );R = max( R, x2 );}n <<= 1; R --;sort( E + 1, E + n + 1, cmp );build( 1, L, R );int ans = 0, lst = 0;for( int i = 1;i <= n;i ++ ) {modify( 1, E[i].l, E[i].r - 1, E[i].op );ans += Fabs( t[1].len - lst ) + 2 * t[1].cnt * ( E[i + 1].h - E[i].h );lst = t[1].len;}printf( "%d\n", ans );}return 0; }Walking Race
POJ3162
用兩次棧模擬dpdpdp求出以每個(gè)點(diǎn)為端點(diǎn)的最長(zhǎng)路徑
用線段樹維護(hù)區(qū)間內(nèi)的路徑最大值/最小值
尺取法,雙指針判斷區(qū)間[l,r][l,r][l,r]是否在mmm限制內(nèi)
#include <stack> #include <cstdio> #include <vector> #include <iostream> using namespace std; #define maxn 1000005 #define lson num << 1 #define rson num << 1 | 1 const int inf = 1e9; int n, m; bool vis[maxn]; int maxlen[maxn]; stack < int > sta; vector < pair < int, int > > G[maxn];struct node { int fa, d, Max, id, sub_max, sub_id;void clear( int f, int dis ) { fa = f, d = dis, Max = id = sub_max = sub_id = 0; } }MS[maxn];void dfs1() {for( int i = 1;i <= n;i ++ ) vis[i] = 0;sta.push( 1 ), MS[1].clear( 0, 0 );while( ! sta.empty() ) {int u = sta.top();if( ! vis[u] )for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i].first, dis = G[u][i].second;if( v == MS[u].fa ) continue;else MS[v].clear( u, dis ), sta.push( v );}else {sta.pop();for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i].first, dis = G[u][i].second;int len = MS[v].Max + dis;if( len > MS[u].Max ) {MS[u].sub_max = MS[u].Max;MS[u].sub_id = MS[u].id;MS[u].Max = len;MS[u].id = v;}else if( len > MS[u].sub_max ) {MS[u].sub_max = len;MS[u].sub_id = v;}}}vis[u] = 1;} }void dfs2() {sta.push( 1 );while( ! sta.empty() ) {int u = sta.top(); sta.pop();for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i].first;if( v == MS[u].fa ) continue;else sta.push( v );}maxlen[u] = MS[u].Max;if( u == 1 ) continue;else {int fa = MS[u].fa, len;if( MS[fa].id == u ) len = MS[fa].sub_max + MS[u].d;else len = MS[fa].Max + MS[u].d;maxlen[u] = max( maxlen[u], len );if( len > MS[u].Max ) {MS[u].sub_max = MS[u].Max;MS[u].sub_id = MS[u].id;MS[u].Max = len;MS[u].id = fa;}else if( len > MS[u].sub_max ) {MS[u].sub_max = len;MS[u].sub_id = fa;}}} }struct tree { int Min, Max; }t[maxn << 2];void build( int num, int l, int r ) {if( l == r ) { t[num].Min = t[num].Max = maxlen[l]; return; }int mid = l + r >> 1;build( lson, l, mid );build( rson, mid + 1, r );t[num].Max = max( t[lson].Max, t[rson].Max );t[num].Min = min( t[lson].Min, t[rson].Min ); }int query_min( int num, int l, int r, int L, int R ) {if( r < L or R < l ) return inf;if( L <= l and r <= R ) return t[num].Min;int mid = l + r >> 1;return min( query_min( lson, l, mid, L, R ), query_min( rson, mid + 1, r, L, R ) ); }int query_max( int num, int l, int r, int L, int R ) {if( r < L or R < l ) return -inf;if( L <= l and r <= R ) return t[num].Max;int mid = l + r >> 1;return max( query_max( lson, l, mid, L, R ), query_max( rson, mid + 1, r, L, R ) ); }int main() {int l, r, minn, maxx;while( ~ scanf( "%d %d", &n, &m ) ) {for( int i = 1;i <= n;i ++ ) G[i].clear();for( int i = 2, fa, d;i <= n;i ++ ) {scanf( "%d %d", &fa, &d );G[fa].push_back( make_pair( i, d ) );}dfs1(), dfs2(), build( 1, 1, n );l = r = 1, minn = maxx = maxlen[1];int ans = 0;while( l <= r and r <= n ) {if( maxx - minn <= m ) {ans = max( ans, r - l + 1 );r ++;minn = min( minn, maxlen[r] );maxx = max( maxx, maxlen[r] );}else {l ++;minn = query_min( 1, 1, n, l, r );maxx = query_max( 1, 1, n, l, r );}if( ans > n - l ) break;}printf( "%d\n", ans );}return 0; }總結(jié)
以上是生活随笔為你收集整理的【地狱副本】数据结构之线段树Ⅲ——区间最值/赋值/修改/历史值操作(HDU5306,Tyvj 1518,【清华集训2015】V,HDU6315,HDU1828,POJ3162)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces Round #74
- 下一篇: 花密帐号密码管理Flower Passw