线段树维护区间 覆盖 :
现在有需求:
有一个长度为N的序列 (* N只要符合我们的线段树复杂度都可以进行维护,而只要能维护出来,基本上都是可用线段树解决)
要对区间 进行标记,标记M段 区间 , 区间可以产生覆盖
求 任意 区间内 被标记的数量
直接维护区间标记是O(N)的复杂度 , 使用线段树花费O(logN) ,则应用到这种类型的结构的题可过。
some 用途列举:
- LCA , 对u , v 两点间的路径都进行标记
- 树链剖分 , 对u, v 两点间的路径进行记录
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
#include <set>
#include <vector>
#include <stack>
#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] 的区间异或和