整理了一下zkw线段树的基本操作:
1.修改元素值:给定x,y,修改a[x]的值为y;
2.查询元素值:给定x,输出a[x]的值;
3.区间增减:给定l,r,x,将从a[l]到a[r](含al和ar),即区间[l,r]中的每个值都加上x;
4.区间求和:给定l,r,输出从a[l]到a[r](含al和ar),即区间[l,r]中的每个元素之和。
#include<cstdio> #include<cstdlib> #include<cctype> #include<cstring> #define LL long long LL x,a,b,c,n,m,pre=1; LL num[10000000],numm[10000000]; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } inline void add(int a,int b) { num[a+=pre]+=b; numm[a]=(a-pre)*num[a]; a>>=1; while(a) { num[a]=num[a<<1]+num[(a<<1)+1]; numm[a]=numm[a<<1]+numm[(a<<1)+1]; a>>=1; } } inline LL query(int a,int b) { LL ans=0; a+=pre-1; b+=pre+1; while(a^b^1) { if(~a&1) ans+=num[a^1]; if(b&1) ans+=num[b^1]; a>>=1; b>>=1; } return ans; } inline LL nquery(int a,int b) { LL ans=0; a+=pre-1; b+=pre+1; while(a^b^1) { if(~a&1) ans+=numm[a^1]; if(b&1) ans+=numm[b^1]; a>>=1; b>>=1; } return ans; } int main() { int i; n=read(); m=read(); n=read(); while(pre<=n) pre<<=1; for(i=pre+1;i<=pre+n;++i) num[i]=read(); for(i=pre+n;i>pre;--i) { num[i]-=num[i-1]; numm[i]=(i-pre)*num[i]; } for(i=pre-1;i>=1;--i) { num[i]=num[i<<1]+num[(i<<1)+1]; numm[i]=numm[i<<1]+numm[(i<<1)+1]; } for(i=1;i<=m;++i) { x=read(); if(x==1) { a=read(),b=read(); add(a,b),add(a+1,-b); printf("-1\n"); } if(x==2) { a=read(); printf("%lld\n",query(1,a)); } if(x==3) { a=read(),b=read(),c=read(); add(a,c),add(b+1,-c); printf("-1\n"); } if(x==4) { a=read(),b=read(); printf("%lld\n",(query(1,b)*(b+1)-nquery(1,b))-query(1,a-1)*a+nquery(1,a-1)); } } printf("\n"); return 0; }
于是作死的做了CODEVS 1954 线段树。
已被saffah前辈虐哭0.0
求大神帮助………………
时间: 2024-10-10 05:11:13