线段树 维护区间 覆盖 , 区间异或 ‘^' (待续)

线段树维护区间  覆盖 :

现在有需求

有一个长度N序列   (* N只要符合我们的线段树复杂度都可以进行维护,而只要能维护出来,基本上都是可用线段树解决

要对区间 进行标记,标记M段 区间区间可以产生覆盖

求 任意  区间内 被标记的数量

 

直接维护区间标记是O(N)的复杂度 , 使用线段树花费O(logN) ,则应用到这种类型的结构的题可过。

some 用途列举:

  • LCA , 对u , v 两点间的路径都进行标记
  • 树链剖分 , 对u, v 两点间的路径进行记录
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define Clear( x , y ) memset( x , y , sizeof(x) );
#define Qcin() std::ios::sync_with_stdio(false);
using namespace std;
typedef long long LL;
const int Maxn = 1e6 + 7;
const int Inf = 1e9 + 7;
LL A[Maxn];
LL N , M;
struct edge{
	LL l , r;
	LL state , sum , lazy;
}tree[Maxn];

void PushUp( LL x ){
	tree[x].sum = max(tree[x].sum , tree[x*2].sum + tree[x*2+1].sum);
}

void Build( LL l , LL r , LL x ){
	tree[x].l = l , tree[x].r = r;
	if( l == r ){
		tree[x].state = A[l];
		tree[x].sum  = tree[x].lazy = 0;
		return;
	}
	LL mid = ( l + r ) / 2;
	Build( l , mid , x * 2 );
	Build( mid + 1 , r , x * 2 + 1 );
	PushUp( x );
}

void PushDown( LL x ){
	tree[x*2].lazy |= tree[x].lazy;
	tree[x*2+1].lazy |= tree[x].lazy;
	tree[x*2].state |= tree[x*2].lazy;
	tree[x*2+1].state |= tree[x*2+1].lazy;
	tree[x].lazy = 0;
}

void Update_line( LL L , LL R , LL add , LL x ){
	if( L <= tree[x].l && tree[x].r <= R ){
		tree[x].state |= add;
		tree[x].lazy |= add;
		tree[x].sum = tree[x].r - tree[x].l + 1;
		return;
	}
	PushDown( x );
	LL mid = ( tree[x].l + tree[x].r ) / 2;
	if( L <= mid )	Update_line( L , R , add , x * 2 );
	if( R > mid )	Update_line( L , R , add , x * 2 + 1 );
	PushUp( x );
}

LL Query( LL L , LL R , LL x ){
	if( L <= tree[x].l && tree[x].r <= R ){
		return tree[x].sum;
	}
	PushDown( x );
	LL mid = ( tree[x].l + tree[x].r ) / 2;
	LL res = 0LL;
	if( L <= mid )	res += Query( L , R , x * 2 );
	if( R > mid )	res += Query( L , R , x * 2 + 1 );
	return res;
}

int main()
{
	scanf(" %lld %lld",&N,&M);
	Build(1 , N , 1);
	for(LL i = 1 ; i <= M ; i++){
		LL u , v;	scanf(" %lld %lld",&u,&v);
		Update_line(u , v , 1 , 1);
	}
	printf("%lld\n",Query(1 , N , 1));
}
/*
100 3
1 15
2 14
3 16


100 5
1 5
6 10
11 15
20 25
21 30
*/

线段树维护区间  '^':

一个长度为N的序列

单点修改某个点的值

查询一段区间区间 a[i ... j] 的区间异或和

 

你可能感兴趣的:(数据结构)