HDU 1698 Just a Hook(线段树的区间修改)
思路:
这题考察线段树的区间修改,如果不做优化会使复杂度非常糟糕,优化的办法就是用lazy-tag
方法。当修改的区间覆盖当前遍历到的区间时,只对当前结点做出修改,不继续深入,并给它做标记,在代码中体现在rcd[]
数组中。当需要继续深入时,采用push_down
方法去更新它的子节点;
代码:
#include<iostream>
using namespace std;
template <class T>
inline bool read(T &ret){
char c; int sgn;
if(c=getchar(),c==EOF) return 0; //EOF
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn; return 1;
}
const int MAX_N=1e5+99;
int sum[MAX_N<<2],rcd[MAX_N<<2];
void push_up(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void push_down(int rt,int m){
if(rcd[rt]){
rcd[rt<<1]=rcd[rt<<1|1]=rcd[rt];
sum[rt<<1]=(m-(m>>1))*rcd[rt];
sum[rt<<1|1]=(m>>1)*rcd[rt];
rcd[rt]=0;
}
}
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
void build(int l,int r,int rt){
rcd[rt]=0;
if(l==r) {sum[rt]=1;return;}
int mid=(l+r)>>1;
build(lson),build(rson);
push_up(rt);
}
void update(int a,int b,int c,int l,int r,int rt){
if(a<=l&&b>=r){
sum[rt]=(r-l+1)*c;
rcd[rt]=c;
return;
}
push_down(rt,r-l+1);
int mid=(l+r)>>1;
if(a<=mid) update(a,b,c,lson);
if(b>mid) update(a,b,c,rson);
push_up(rt);
}
int main(){
int kase; read(kase);
for(int i=1;i<=kase;i++){
int n,q; read(n); read(q);
build(1,n,1);
while(q--){
int x,y,z;
read(x); read(y); read(z);
update(x,y,z,1,n,1);
}
printf("Case %d: The total value of the hook is %d.\n",i,sum[1]);
}
return 0;
}