数据结构二之线段树Ⅱ——KiKi‘s K-Number,ball,The Child and Sequence,「雅礼集训 2017 Day1」市场,Atlantis
值域線段樹(shù)+勢(shì)能線段樹(shù)+掃描線
- KiKi's K-Number
- ball
- The Child and Sequence
- 「雅禮集訓(xùn) 2017 Day1」市場(chǎng)
- Atlantis
KiKi’s K-Number
HDU-2852
權(quán)值線段樹(shù)維護(hù)插入刪除很簡(jiǎn)單
對(duì)于查詢大于xxx的第kkk個(gè),可以不用二分,轉(zhuǎn)化一下
先查小于等于xxx的個(gè)數(shù)cntcntcnt,然后查排名為第cnt+kcnt+kcnt+k個(gè)值
#include <cstdio> #define maxn 100000 #define lson num << 1 #define rson num << 1 | 1 struct node {int sum, cnt; }t[maxn << 2 | 1];void build( int num, int l, int r ) {t[num].sum = t[num].cnt = 0;if( l == r ) return;int mid = l + r >> 1;build( lson, l, mid );build( rson, mid + 1, r ); }void modify( int num, int l, int r, int pos, int v ) {if( l == r ) { t[num].cnt += v, t[num].sum += v; return; }int mid = l + r >> 1;if( pos <= mid ) modify( lson, l, mid, pos, v );else modify( rson, mid + 1, r, pos, v );t[num].sum = t[lson].sum + t[rson].sum; }int query_cnt( int num, int l, int r, int pos ) {if( l == r ) return t[num].cnt;int mid = l + r >> 1;if( pos <= mid ) return query_cnt( lson, l, mid, pos );else return query_cnt( rson, mid + 1, r, pos ); }int query( int num, int l, int r, int k ) {if( l == r ) return l;int mid = l + r >> 1;if( k <= t[lson].sum ) return query( lson, l, mid, k );else return query( rson, mid + 1, r, k - t[lson].sum ); }int query( int num, int l, int r, int L, int R ) {if( R < l || r < L ) return 0;if( L <= l && r <= R ) return t[num].sum;int mid = l + r >> 1;return query( lson, l, mid, L, R ) + query( rson, mid + 1, r, L, R ); }int main() {int n, opt, x, k, cnt, ans;while( ~ scanf( "%d", &n ) ) {build( 1, 1, maxn );while( n -- ) {scanf( "%d %d", &opt, &x );switch( opt ) {case 0 : { modify( 1, 1, maxn, x, 1 ); break; }case 1 : {if( ! query_cnt( 1, 1, maxn, x ) ) printf( "No Elment!\n" );else modify( 1, 1, maxn, x, -1 );break;}case 2 : {scanf( "%d", &k );cnt = query( 1, 1, maxn, 1, x );ans = query( 1, 1, maxn, cnt + k );if( ans == maxn ) printf( "Not Find!\n" );else printf( "%d\n", ans );break;}}}}return 0; }ball
CF-12D
虛假的三維偏序
- 以BBB離散化后作權(quán)值線段樹(shù)下標(biāo)
- 按III降序排列,相同的按RRR升序排列
- 查BiB_iBi?后面[x+1,N][x+1,N][x+1,N]的RRR最大值,如果最大值大于RiR_iRi?,那么iii就會(huì)出局
- 首先BiB_iBi?后面,滿足Bi<B′B_i<B'Bi?<B′
- 其次按照III排序,天然滿足Ii<I′I_i<I'Ii?<I′
- 最后最大值Ri<R′R_i<R'Ri?<R′
- 將RiR_iRi?插到BiB_iBi?對(duì)應(yīng)下標(biāo)上[1,x][1,x][1,x],維護(hù)區(qū)間RRR最大值
The Child and Sequence
CF-438D
區(qū)間求和很好維護(hù)
至于取模操作,由輾轉(zhuǎn)相除法可知,取模后結(jié)果不超過(guò)原數(shù)的一半
所以最多log?\loglog次后取模就對(duì)其沒(méi)有意義了
考慮維護(hù)區(qū)間最大值,如果最大值都比取模的數(shù)小,那么這個(gè)區(qū)間就沒(méi)有操作的意義
否則就暴力往下取模
#include <cstdio> #include <iostream> using namespace std; #define int long long #define maxn 100005 #define lson num << 1 #define rson num << 1 | 1 struct node {int sum, Max; }t[maxn << 2]; int a[maxn];void build( int num, int l, int r ) {if( l == r ) { t[num].sum = t[num].Max = a[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].sum = t[lson].sum + t[rson].sum; }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;int mid = l + r >> 1;return query( lson, l, mid, L, R ) + query( rson, mid + 1, r, L, R ); }void modify( int num, int l, int r, int L, int R, int v ) {if( t[num].Max < v or R < l or r < L ) return;if( l == r ) { t[num].Max = t[num].sum = t[num].Max % v; return; }int mid = l + r >> 1;modify( lson, l, mid, L, R, v );modify( rson, mid + 1, r, L, R, v );t[num].Max = max( t[lson].Max, t[rson].Max );t[num].sum = t[lson].sum + t[rson].sum; }void modify( int num, int l, int r, int pos, int val ) {if( l == r ) { t[num].Max = t[num].sum = val; return; }int mid = l + r >> 1;if( pos <= mid ) modify( lson, l, mid, pos, val );else modify( rson, mid + 1, r, pos, val );t[num].Max = max( t[lson].Max, t[rson].Max );t[num].sum = t[lson].sum + t[rson].sum; }signed main() {int n, m, opt, l, r, x, k;scanf( "%lld %lld", &n, &m );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] ); build( 1, 1, n );while( m -- ) {scanf( "%lld", &opt );switch ( opt ) {case 1 : {scanf( "%lld %lld", &l, &r );printf( "%lld\n", query( 1, 1, n, l, r ) );break;}case 2 : {scanf( "%lld %lld %lld", &l, &r, &x );modify( 1, 1, n, l, r, x );break;}case 3 : {scanf( "%lld %lld", &x, &k );modify( 1, 1, n, x, k );break;}}}return 0; }「雅禮集訓(xùn) 2017 Day1」市場(chǎng)
LOJ#6029
對(duì)于下取整的維護(hù),考慮Δ=max??maxxk?=min??minnk?\Delta=\rm max-\lfloor\frac{maxx}{k}\rfloor=min-\lfloor\frac{minn}{k}\rfloorΔ=max??kmaxx??=min??kminn??
則整個(gè)區(qū)間的每個(gè)數(shù)都會(huì)?Δ-\Delta?Δ,可以用區(qū)間加標(biāo)記記錄
否則就仍然暴力往下除
利用勢(shì)能分析,足以通過(guò)
推薦好妹妹的本題勢(shì)能分析題解戳我哦(づ ̄3 ̄)づ╭?~
#include <cmath> #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 sum, Min, Max, tag; }t[maxn << 2]; int a[maxn];void pushdown( int num, int l, int r ) {if( ! t[num].tag ) return;int mid = l + r >> 1;t[lson].Max += t[num].tag;t[lson].Min += t[num].tag;t[lson].tag += t[num].tag;t[lson].sum += t[num].tag * ( mid - l + 1 );t[rson].Max += t[num].tag;t[rson].Min += t[num].tag;t[rson].tag += t[num].tag;t[rson].sum += t[num].tag * ( r - mid );t[num].tag = 0; }void pushup( int num ) {t[num].Min = min( t[lson].Min, t[rson].Min );t[num].Max = max( t[lson].Max, t[rson].Max );t[num].sum = t[lson].sum + t[rson].sum; }void modify1( int num, int l, int r, int L, int R, int v ) {if( R < l or r < L ) return;if( L <= l and r <= R ) {t[num].Min += v;t[num].Max += v;t[num].tag += v;t[num].sum += v * ( r - l + 1 );return;}pushdown( num, l, r );int mid = l + r >> 1;modify1( lson, l, mid, L, R, v );modify1( rson, mid + 1, r, L, R, v );pushup( num ); }void modify2( int num, int l, int r, int L, int R, int v ) {if( r < L or R < l ) return;if( L <= l and r <= R ) {int maxx = ( int )floor( t[num].Max * 1.0 / v );int minn = ( int )floor( t[num].Min * 1.0 / v );if( t[num].Max - maxx == t[num].Min - minn ) {int x = t[num].Max - maxx;t[num].tag -= x;t[num].Max = maxx;t[num].Min = minn;t[num].sum -= ( r - l + 1 ) * x;return;}}pushdown( num, l, r );int mid = l + r >> 1;modify2( lson, l, mid, L, R, v );modify2( rson, mid + 1, r, L, R, v );pushup( num ); }pair < int, int > query( int num, int l, int r, int L, int R ) {if( r < L or R < l ) return make_pair( inf, 0 );if( L <= l and r <= R ) return make_pair( t[num].Min, t[num].sum );pushdown( num, l, r );int mid = l + r >> 1;pair < int, int > ans1 = query( lson, l, mid, L, R );pair < int, int > ans2 = query( rson, mid + 1, r, L, R );return make_pair( min( ans1.first, ans2.first ), ans1.second + ans2.second ); }void build( int num, int l, int r ) {if( l == r ) { t[num].Max = t[num].Min = t[num].sum = a[l], t[num].tag = 0; return; }int mid = l + r >> 1;build( lson, l, mid );build( rson, mid + 1, r );pushup( num ); }signed main() {int n, Q, opt, l, r, x;scanf( "%lld %lld", &n, &Q );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] );build( 1, 1, n );while( Q -- ) {scanf( "%lld %lld %lld", &opt, &l, &r );l ++, r ++;switch ( opt ) {case 1 : { scanf( "%lld", &x ); modify1( 1, 1, n, l, r, x ); break; }case 2 : { scanf( "%lld", &x ); modify2( 1, 1, n, l, r, x ); break; }case 3 : { printf( "%lld\n", query( 1, 1, n, l, r ).first ); break; }case 4 : { printf( "%lld\n", query( 1, 1, n, l, r ).second ); break; }}}return 0; }Atlantis
HDU-1542
線段樹(shù)維護(hù)掃描線的模板題
離散化xxx坐標(biāo),矩陣左右成為線段樹(shù)區(qū)間,遇到矩陣的下面一條線+1+1+1,上面一條線?1-1?1
掃描線是維護(hù)線段(可以看做是維護(hù)邊,信息放在兩點(diǎn)間),平常線段樹(shù)是維護(hù)點(diǎn)(信息發(fā)在單點(diǎn)上)
所以寫(xiě)法會(huì)有邊界的丟丟不同
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define maxn 205 #define lson num << 1 #define rson num << 1 | 1 struct node {double l, r, h; int op;node(){}node( double L, double R, double H, int Op ) {l = L, r = R, h = H, op = Op;} }g[maxn]; double x[maxn], t[maxn << 2]; int tag[maxn << 2];bool cmp( node u, node v ) { return u.h < v.h; }void pushup( int num, int l, int r ) {if( tag[num] ) t[num] = x[r] - x[l];else if( l + 1 == r ) t[num] = 0;else t[num] = t[lson] + t[rson]; }void modify( int num, int l, int r, int L, int R, int val ) {if( R <= l or r <= L ) return;if( L <= l and r <= R ) {tag[num] += val;pushup( num, l, r );return;}int mid = l + r >> 1;modify( lson, l, mid, L, R, val );modify( rson, mid, r, L, R, val );pushup( num, l, r ); }int main() {int T = 0, n; double x1, y1, x2, y2;while( scanf( "%d", &n ) and n ) {for( int i = 1;i <= n;i ++ ) {scanf( "%lf %lf %lf %lf", &x1, &y1, &x2, &y2 );x[i] = x1, x[i + n] = x2;g[i] = node( x1, x2, y1, 1 );g[i + n] = node( x1, x2, y2, -1 );}n <<= 1;sort( x + 1, x + n + 1 );sort( g + 1, g + n + 1, cmp );int m = unique( x + 1, x + n + 1 ) - x - 1;memset( t, 0, sizeof( t ) );memset( tag, 0, sizeof( tag ) );double ans = 0;for( int i = 1;i < n;i ++ ) {int l = lower_bound( x + 1, x + m + 1, g[i].l ) - x;int r = lower_bound( x + 1, x + m + 1, g[i].r ) - x;modify( 1, 1, m, l, r, g[i].op );ans += t[1] * ( g[i + 1].h - g[i].h );}printf( "Test case #%d\nTotal explored area: %.2f\n\n", ++ T, ans );}return 0; }總結(jié)
以上是生活随笔為你收集整理的数据结构二之线段树Ⅱ——KiKi‘s K-Number,ball,The Child and Sequence,「雅礼集训 2017 Day1」市场,Atlantis的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2022虎年春节祝福语顺口溜
- 下一篇: [AtCoder Beginner Co