整理了一下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
求大神帮助………………
原文地址:http://blog.csdn.net/wxjlzbcd/article/details/42833741