Codevs 1081 線段樹練習 2
阿新 • • 發佈:2019-02-15
區間修改 單點查詢
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define LL long long using namespace std; //輸出優化 begin inline void wprint(int x){ if (x>9) wprint(x/10); putchar(x%10+'0'); } inline void print(int x){ if (x<0) x=-x,putchar('-'); wprint(x); putchar('\n'); } //輸出優化 end //讀入優化 begin inline int wread(){ char c(getchar());int wans(0),flag(1); while (c<'0'||c>'9'){if (c=='-') flag=-1;c=getchar();} while (c>='0'&&c<='9'){wans=(wans<<3)+(wans<<1)+(c^48);c=getchar();} return wans*=flag; } inline LL ll_wread(){ char c(getchar());LL wans((LL)0),flag((LL)1); while (c<'0'||c>'9'){if (c=='-') flag=-1;c=getchar();} while (c>='0'&&c<='9'){wans=(wans<<3)+(wans<<1)+(c^48);c=getchar();} return wans*=flag; } //讀入優化 end struct node{int l,r,len;LL ans,lazy1;}e[400004]; int n,m; void make_tre(int a,int l,int r){ e[a].l=l; e[a].r=r; e[a].ans=e[a].lazy1=0; if (l==r){e[a].ans=ll_wread(); e[a].len=(LL)1; return ;} int mid( l+r >>1 ),lson(a<<1),rson(a<<1|1); make_tre(lson, l, mid); make_tre(rson, mid+1, r); e[a].ans=e[lson].ans + e[rson].ans; e[a].len=e[lson].len + e[rson].len; } void xia_fang(int a){ int lson(a<<1),rson(a<<1|1); e[lson].lazy1+=e[a].lazy1;e[lson].ans+=e[lson].len*e[a].lazy1; e[rson].lazy1+=e[a].lazy1;e[rson].ans+=e[rson].len*e[a].lazy1; e[a].lazy1=0; } void add_qu (int a, int l, int r, LL k ){ if (e[a].l>=l && e[a].r<=r ){e[a].lazy1+=k; e[a].ans+=e[a].len*k; return;} if (e[a].lazy1) xia_fang(a);//lazy標記下放操作 詳見48行 int mid(e[a].l+e[a].r>>1),lson(a<<1),rson(a<<1|1); if (r<=mid) add_qu(lson,l,r,k); else if (l>mid) add_qu(rson,l,r,k); else add_qu(lson,l,r,k),add_qu(rson,l,r,k); e[a].ans=e[lson].ans+e[rson].ans; return ; } LL fnd_dian (int a,int pos){ if (e[a].l==pos && e[a].r==pos) {return e[a].ans;} if (e[a].lazy1) xia_fang(a);//下放操作 詳見48行 int mid(e[a].l+e[a].r>>1),lson(a<<1),rson(a<<1|1); if (pos<=mid) return fnd_dian(lson,pos); else if (pos>mid) return fnd_dian(rson,pos); } int main (){ n=wread(); make_tre(1,1,n); m=wread(); while (m--){ int opr=wread(); if (opr==1){ int x=wread(),y=wread();LL k=ll_wread();//區間[x,y] 每個數+k add_qu(1, x, y, k); } else { int pos=wread();//查詢第i個數的值 print(fnd_dian(1, pos)); } } return 0; }