有自己的一点理解
#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[N],tag[N]; 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 ",query(1,1,n,l,l)); } } return 0; }