单点修改,区间求和,立即推 树状数组
顺便练习一下线段树
树状数组
#include<bits/stdc++.h>
using namespace std;
//int sev[10000];
typedef long long ll;
const int ma=200001;
int p[4*ma];
long long sum[4*ma];
ll suma;
int t;
int lowerbit(int x)
{
return x&(-x);
}
ll qsum(int x)
{
ll res=0;
while(x>0)
{
res+=sum[x];
x-=lowerbit(x);
}
return res;
}
void add(int x,ll d){
while(x<=t)
{
sum[x]+=d;
x+=lowerbit(x);
}
}
int main()
{
int cou=0;
while(scanf("%d",&t) && t!=0)
{
memset(p,0,sizeof p);
memset(sum,0,sizeof sum);
for(int i=1;i<=t;i++)
{
scanf("%d",&p[i]);
add(i,p[i]);
}
if(cou!=0){
printf("\n");
}
printf("Case %d:\n",++cou);
char c[10];
while(scanf("%s",c) ){
if(c[0]=='M'){
suma=0;
int a, b;
scanf("%d%d",&a,&b);
suma=qsum(b)-qsum(a)+p[a];
printf("%lld\n",suma);
}
if(c[0]=='S')
{
int a,b; scanf("%d%d",&a,&b);
add(a,(ll)(-1*p[a]));
p[a]=b;
add(a,(ll)b);
}
if(c[0]=='E'){ break;}
}
}
return 0;
}
线段树
#include<bits/stdc++.h>
using namespace std;
//int sev[10000];
const int ma=200001;
int p[4*ma];
long long sum[4*ma];
long long suma;
void maintain(int o,int l,int r){
sum[o]=0;
if(l==r) sum[o]=p[o] ;
else
sum[o]=sum[o*2]+sum[o*2+1];
}
void build(int o,int l,int r,int L,int R ,int pot){
if(L <=l && r<=R)
{
p[o]=pot;
}
else{
int m=(l+r)/2;
if(L<=m)
build(o*2,l,m,L,R,pot);
if(m<R)
build(o*2+1,m+1,r,L,R,pot);
}
maintain(o,l,r);
}
void quiry(int o,int l,int r,int L,int R){
if(L<=l && r<=R)
{
suma+=sum[o];
return ;
}
int m=(l+r)/2;
if(L<=m)
quiry(o*2,l,m,L,R);
if(m<R)
quiry(o*2+1,m+1,r,L,R);
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int t;
int cou=0;
while(scanf("%d",&t) && t!=0)
{
for(int i=1;i<=t;i++)
{
int pot; scanf("%d",&pot);
build(1,1,t,i,i,pot);
}
if(cou!=0){
printf("\n");
}
printf("Case %d:\n",++cou);
char c[10];
while(scanf("%s",c) ){
if(c[0]=='M'){
suma=0;
int a, b;
scanf("%d%d",&a,&b);
quiry(1,1,t,a,b); // 求 a--b 的和
printf("%lld\n",suma);
}
if(c[0]=='S')
{
int a,b; scanf("%d%d",&a,&b);
build(1,1,t,a,a,b); // 在a 处改成b
}
if(c[0]=='E'){ break;}
}
}
return 0;
}