您的位置:首页 > 其它

HDU_1698 Just a Hook(线段树+lazy标记)

2015-08-23 21:54 176 查看
题目请点我

题解:

接触到的第一到区间更新,需要用到lazy标记,典型的区间着色问题。

lazy标记详情请参考博客:http://ju.outofmemory.cn/entry/99351

简单讲就是被lazy标记的非叶子节点所包含的所有叶子节点具有相同的性质,当更新或查询到该区间时,不再向下递归,仅对当前节点的lazy标记进行修改。

update :

如果当前区间刚好完全在目的区间内:看当前节点是否被标记,若未被标记,或者被标记了但是与要更新类型相同,不再向下更新,仅标记当前节点;若当前节点已经被标记且与要更新类型不同,执行pushdown操作,标记下移,递归进行更新。

query:

如果当前节点区间在目的区间内(其实一定在,因为题目要求1~N总的价值),若节点被标记,返回segTree[i]*(r+1-l);若当前节点未被标记或者区间不能完全覆盖,递归求解。

代码实现:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAX 100010
#define LCHILD(x) x<<1
#define RCHILD(x) x<<1|1
#define MID(x,y) (x+y)>>1

using namespace std;

int T;
int res;
int N,Q;
int segTree[MAX<<2|1];
void pushdown(int root);
void build(int root,int l,int r);
int query(int a,int b,int l,int r,int root);
void update(int a,int b,int l,int r,int root,int type);
int main()
{
scanf("%d",&T);
for( int t = 1; t <= T; t++ ){
scanf("%d",&N);
scanf("%d",&Q);
build(1,1,N);
while( Q-- ){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
update(a,b,1,N,1,c);
}
int res = query(1,N,1,N,1);
printf("Case %d: The total value of the hook is %d.\n",t,res);
}
return 0;
}

void build(int root,int l,int r){
if( l == r ){
segTree[root] = 1;
return ;
}
int mid = MID(l,r);
build(LCHILD(root),l,mid);
build(RCHILD(root),mid+1,r);
//非叶子节点初始为0,表示不标记
segTree[root] = 0;
}

void update(int a,int b,int l,int r,int root,int type){
//不在当前区间
if( l > b || r < a ){
return ;
}
//更新区间完全在当前区间内或者type相同
if( (l >= a && r <= b) || segTree[root] == type ){
segTree[root] = type;
return ;
}
//当前节点被标记但是type不同
if( segTree[root] != 0 ){
pushdown(root);
}
int mid = MID(l,r);
update(a,b,l,mid,LCHILD(root),type);
update(a,b,mid+1,r,RCHILD(root),type);
return ;
}

int query(int a,int b,int l,int r,int root){
//不在当前区间
if( l > b || r < a ){
return 0;
}
int mid = MID(l,r);
if( l >= a && r <= b ){
if( segTree[root] != 0 ){
//闭区间[l,r]
return segTree[root]*(r+1-l);
}
else{
return query(a,b,l,mid,LCHILD(root))+query(a,b,mid+1,r,RCHILD(root));
}
}
else{
return query(a,b,l,mid,LCHILD(root))+query(a,b,mid+1,r,RCHILD(root));
}
}

void pushdown(int root){
segTree[LCHILD(root)] = segTree[root];
segTree[RCHILD(root)] = segTree[root];
segTree[root] = 0;
return ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树 lazy