带有down的线段树模板
数组开的是2*n
左孩纸是 n+1
右孩纸是n+(左孩子区间长度+1)*2
线段树题目
I Hate It HDU - 1754
敌兵布阵 HDU - 1166
Color the ball HDU - 1556
#include<iostream>
#define max 100
using namespace std;
struct node {
int left ,right,w,f; //f是懒标记
};
node tree[max*2+10];
void bulid(int l,int r,int k){
tree[k].left=l;
tree[k].right=r;
if(l==r){
cin>>tree[k].w;
return ;
}
int mid=(l+r)/2;
bulid(l,mid,k+1);
bulid(mid+1,r,k+(mid-l+1)*2);
tree[k].w=tree[k+1].w+tree[k+(mid-l+1)*2].w;
}
int ask(int k,int index){ //单点查询 返回第k个元素的值
if(tree[index].left==tree[index].right){
return tree[index].w;
}
int mid=(tree[index].left+tree[index].right)/2;
if(mid>=k)
ask(k,index+1);
else
ask(k,index+((mid-tree[index].left)+1)*2);
}
void add(int k,int index,int add_){ //单点修改 修改第k个元素的值
tree[index].w+=add_;
if(tree[index].left==tree[index].right){
return;
}
int mid=(tree[index].left+tree[index].right)/2;
if(mid>=k){
add(k,index+1,add_);
}
else {
add(k,index+((mid-tree[index].left)+1)*2,add_);
}
}
void down(int index){ ///tree[index].f 指的是未更新子节点,自己本身已经更新了
tree[index+1].f+=tree[index].f;
int index_right=((tree[index].left+tree[index].right)/2-tree[index].left+1)*2;
tree[index_right].f+=tree[index].f;
tree[index+1].w+=tree[index].f*(tree[index+1].right-tree[index+1].left+1);
tree[index_right].w+=tree[index].f*(tree[index_right].right-tree[index_right].left+1);
tree[index].f=0;
}
int request(int ll,int rr,int index){
int left=tree[index].left;
int right=tree[index].right;
if(left==ll&&right==rr){
return tree[index].w;
}
int mid=(left+right)/2;
if(mid>=rr){ //【ll,rr】区间是【left,mid】 的子区间
if(tree[index].f)
down(index);
return request(ll,rr,index+1);
}
else if(mid<ll){ //【ll,rr】区间是【mid,right】的子区间
if(tree[index].f)
down(index);
return request(ll,rr,index+(mid-left+1)*2);
}
else { //【ll,rr】 区间包括了mid
if(tree[index].f)
down(index);
return request(ll,mid,index+1)+request(mid+1,rr,index+(mid-left+1)*2);
}
}
void add_interval(int ll,int rr,int index,int num){//num是给区间【ll,rr】 中每个点加的数
cout<<ll<<" "<<rr<<" "<<index <<" "<<num<<endl;
int left=tree[index].left;
int right=tree[index].right;
if(left==ll&&right==rr){
tree[index].w+=(right-left+1)*num;
tree[index].f=num;
return ;
}
int mid=(left+right)/2;
if(mid>=rr){ //【ll,rr】区间是【left,mid】 的子区间
add_interval(ll,rr,index+1,num);
}
else if(mid<ll){ //【ll,rr】区间是【mid,right】的子区间
add_interval(ll,rr,index+(mid-left+1)*2,num);
}
else { //【ll,rr】 区间包括了mid
add_interval(ll,mid,index+1,num);
add_interval(mid+1,rr,index+(mid-left+1)*2,num);
}
}
int main(){
int n,m;
cin>>n;
bulid(1,n,1);
for(int i=1;i<=9;i++)
cout<<i<<" "<<tree[i].left<<" "<<tree[i].right<<" "<<tree[i].w<<endl;
add(1,1,1);
for(int i=1;i<=9;i++)
cout<<i<<" "<<tree[i].left<<" "<<tree[i].right<<" "<<tree[i].w<<endl;
return 0;
}