您的位置:首页 > 其它

自己写的 线段树 的板子

2016-05-20 19:34 323 查看
有自己的一点理解

#include<cstdio>
#include<iostream>
using namespace std;
#define N 801000//至少开3倍空间,一般是*4
#define mid ((l+r)>>1)
#define lc (k<<1)
#define rc (k<<1|1)
#define ll long long//数据范围要求
ll a
,tag
;
ll read(){
register ll f=1,x=0;
register char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
void ins(int k,int l,int r,/*int i,*/int val){
if(l==r){a[k]=val;return;}
//if(i<=mid) 维护区
ins(lc,l,mid,/*i,*/val);
//else 维护区
ins(rc,mid+1,r,/*i,*/val);
a[k]=a[lc]+a[rc];//反栈change
}
void pushdown(int k,int l,int r){
if(!tag[k]) return ;
/*a[lc]+=tag[k]*(mid-l+1);
a[rc]+=tag[k]*(r-mid);    维护区
tag[lc]+=tag[k];tag[rc]+=tag[k];*/
tag[k]=0;//标记清零
}
void add(int k,int l,int r,int x,int y,int val){
if(l==x&&r==y){
/*tag[k]+=val;a[k]+=(r-l+1)*val;*/
//维护区 --看题目有无val
return ;
}
pushdown(k,l,r);//注意下放标记
if(y<=mid) add(lc,l,mid,x,y,val);//分 左、右、中 三种情况
else if(x>mid) add(rc,mid+1,r,x,y,val);
else add(lc,l,mid,x,mid,val),add(rc,mid+1,r,mid+1,y,val);
a[k]=a[lc]+a[rc];//反栈change
}
ll query(int k,int l,int r,int x,int y){
if(l==x&&r==y) return a[k];
pushdown(k,l,r);//不明白为什么必须有
if(y<=mid) return query(lc,l,mid,x,y);//分 左、右、中 三种情况
else if(x>mid) return query(rc,mid+1,r,x,y);
else return (query(lc,l,mid,x,mid)+query(rc,mid+1,r,mid+1,y));
}
int main(){
ll n=read(),b;//[1..n]
/*for(ll i=1;i<=n;i++) b=read(),ins(1,1,n,i,b);
看题目建树
*/
ll m=read();//操作数
for(ll i=1;i<=m;i++){
ll opt=read();
if(opt==1){
ll l=read(),r=read(),val=read();
//if(l>r) swap(l,r);//看题目是否保证给出数据l<r
add(1,1,n,l,r,val);
}
else{
ll l=read();
//if(l>r) swap(l,r);
printf("%lld\n",query(1,1,n,l,l));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: