线段树(等级2,待进阶)

Posted $mathcal{Yubai}$

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树(等级2,待进阶)相关的知识,希望对你有一定的参考价值。

1.学了个标记永久化,用处有限,但是也有用
这里详解
code

#include <cstring>
#include <cstdio>
#include <algorithm>	
#define int long long		
#define R register int
#define printf tz1 = printf

using namespace std ;
const int N = 1e5 + 10 ;
typedef long long L ;
typedef double D ;

inline int read(){
	int w = 0 ; bool fg = 0 ; char ch = getchar() ;
	while( ch > \'9\' || ch < \'0\' ) fg |= ( ch == \'-\' ) , ch = getchar() ;
	while( ch >= \'0\' && ch <= \'9\' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - \'0\' ) , ch = getchar() ;
	return fg ? -w : w ; 
}

int tz1 , n , m , c [N] , l , r , k , w ;
struct T{ int l , r , data , lz ; } t [N << 2] ;

void build( int x , int l , int r ){
	t [x].l = l , t [x].r = r ;
	if( l == r ){ t [x].data += c [l] ; return ; }
	int mid = ( l + r ) >> 1 ;
	build( x << 1 , l , mid ) ;
	build( x << 1 | 1 , mid + 1 , r ) ;
	t [x].data = t [x << 1].data + t [x << 1 | 1].data ; 
}

inline int ask( int x , int l , int r ){
//	printf( "ASK%lld %lld %lld %lld %lld %lld\\n" , t [x].data , t [x].lz , l , r , t [x].l , t [x].r ) ;
	if( t [x].l >= l && t [x].r <= r ) return t [x].data + t [x].lz * ( t [x].r - t [x].l + 1 ) ; 
	int ans = t [x].lz * ( min( r , t [x].r ) - max( l , t [x].l ) + 1 ) ;
	int mid = ( t [x].l + t [x].r ) >> 1 ;
	if( l <= mid ) ans += ask ( x << 1 , l , r ) ;
	if( r > mid ) ans += ask ( x << 1 | 1 , l , r ) ;
	return ans ;
}

inline void add( int x , int l , int r , int k ){
//	printf( "%lld %lld %lld %lld %lld\\n" , x , t [x].l , t [x].r , l , r ) ;
	if( t [x].l >= l && t [x].r <= r ){ t [x].lz += k ; return ; } 
	t [x].data += ( min( t [x].r , r ) - max( t [x].l , l ) + 1 ) * k ;
	int mid = ( t [x].l + t [x].r ) >> 1 ;
	if( l <= mid ) add( x << 1 , l , r , k ) ;
	if( r > mid ) add( x << 1 | 1 , l , r , k ) ;
}
 
void sc(){
	n = read() , m = read() ;
	for( R i = 1 ; i <= n ; i ++ ) c [i] = read() ;
	build( 1 , 1 , n ) ;
}

void work(){
	while( m -- ){
		int k = read() ;
		if( k == 1 ) l = read() , r = read() , w = read() , add( 1 , l , r , w ) ;
		else l = read() , r = read() , printf( "%lld\\n" , ask( 1 , l , r ) ) ;
	}
}

signed main(){
	sc() ;
	work() ;
	return 0 ; 
}

2.权值线段树,动态开点,合并先挖个坑

以上是关于线段树(等级2,待进阶)的主要内容,如果未能解决你的问题,请参考以下文章

[数据结构] 主席树初识(理论,代码待补)

线段树模板(待补充)

C++ 树进阶系列之线段树和它的延迟更新

[模板]洛谷T3373 线段树 模板2

可持久化线段树(待补充)

线段树