您的位置:首页 > 其它

uva 12086 线段树or树状数组练习

2017-08-01 10:09 274 查看

题目链接   https://vjudge.net/problem/34215/origin

这个题就是线段树裸题,有两种操作,实现单点更新和区间和的查找即可,这里第一次学习使用树状数组完成。

二者相比,BIT无论从时间,空间还是代码量考虑都要优于ST,所以遇见这种求解区间和的操作考虑使用BIT。

/*线段树 250 ms*/

#include<bits/stdc++.h>
using namespace std;
#define M ((L+R)>>1)
#define lc (id<<1)
#define rc ((id<<1)|1)
int sumv[(200000<<2)+10];
void build(int L,int R,int id)
{
if(L==R){scanf("%d",&sumv[id]);return;}
build(L,M,lc);
build(M+1,R,rc);
sumv[id]=sumv[lc]+sumv[rc];
}
void update(int L,int R,int id,int x,int y)
{
if(L==R) {sumv[id]=y;return;}
if(x<=M)update(L,M,lc,x,y);
else update(M+1,R,rc,x,y);
sumv[id]=sumv[lc]+sumv[rc];
}
int ask(int L,int R,int id,int l,int r)
{
if(L>=l&&R<=r) {return sumv[id];}
if(r<=M) return ask(L,M,lc,l,r);
else if(l>M) return ask(M+1,R,rc,l,r);
else return ask(L,M,lc,l,r)+ask(M+1,R,rc,l,r);
}
int main()
{
int N,i,j,x,y,k=0;
char s[100];
while(cin>>N&&N){
build(1,N,1);
if(k>0) puts("");
printf("Case %d:\n",++k);
while(scanf("%s",s)!=EOF){
if(!strcmp(s,"END")) break;
scanf("%d%d",&x,&y);
if(!strcmp(s,"M")) printf("%d\n",ask(1,N,1,x,y));
else update(1,N,1,x,y);
}
}
return 0;
}

/*树状数组 180ms  */

#include<bits/stdc++.h>
using namespace std;
int sumv[200000+15],n;
int a[200000+15];
int lowbit(int x){return x&-x;}
int sum(int x)
{
int ret=0;
while(x>0){
ret+=sumv[x];
x-=lowbit(x);
}
return ret;
}
void add(int x,int d)
{
while(x<=n){
sumv[x]+=d;
x+=lowbit(x);
}
}
int main()
{
int k=0;
while(scanf("%d",&n)!=EOF&&n){memset(sumv,0,sizeof(sumv));
for(int i=1;i<=n;++i){
int x;
scanf("%d",&x);
a[i]=x;
add(i,x);
}
char s[112];
if(k>0) puts("");
printf("Case %d:\n",++k);
while(scanf("%s",s)!=EOF){
if(!strcmp(s,"END")) break;
int x,y;
scanf("%d%d",&x,&y);
if(s[0]=='M'){
printf("%d\n",sum(y)-sum(x-1));
}
else{
add(x,y-a[x]);
a[x]=y;
}
}
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: