今天本打算学VAL,结果为了把接口写得好看一些不得不和指针纠结——最后没写出来 :(
不过学习了SEGMENT TREE,还算是有收获。
我发现自己coding很差劲 :(
/*
* HDU 1166 敌兵布阵
* mike-w
* 2011-8-14
* ---------------------
* hint:segment tree
* PS:交上去发现78ms,不是很快,最快31ms
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 300000
#define BUF_SIZE 50
#define L 0
#define R 1
#define SUM 2
long seg[MAXSIZE][3];
/*
* build a segment tree
* we assume x1<x2
* r stands for root
*/
int build(long r,long x1,long x2)
{
seg[r][L]=x1;
seg[r][R]=x2;
seg[r][SUM]=0;
if(x1==x2)
return 0;
else if(x2-x1==1)
{
build(r<<1,x1,x1);
build((r<<1)+1,x2,x2);
}
else
{
long mid=(x1+x2)>>1;
build(2*r,x1,mid);
build(2*r+1,mid+1,x2);
}
return 0;
}
int add(long id,long n)
{
long x1,x2,mid,r;
r=1;
x1=seg[r][L];
x2=seg[r][R];
mid=(x1+x2)>>1;
while(x2!=x1)
{
seg[r][SUM]+=n;
if(id<=mid)
r<<=1;
else
r=(r<<1)+1;
x1=seg[r][L];
x2=seg[r][R];
mid=(x1+x2)>>1;
}
seg[r][SUM]+=n;
return 0;
}
/*
* similiar to function build()
* but they DIFFER
*/
long query(long r,long x1,long x2)
{
long left=seg[r][L],
right=seg[r][R],
mid=(left+right)>>1;
if(x1==left&&x2==right)
return seg[r][SUM];
else if(x2<=mid)
return query(r<<1,x1,x2);
else if(x1>mid)
return query((r<<1)+1,x1,x2);
else
return query(r<<1,x1,mid)+query((r<<1)+1,mid+1,x2);
}
int main(void)
{
int ncase,ccase=0;
long N,i,j;
char buf[BUF_SIZE];
#ifndef ONLINE_JUDGE
freopen("1166.in","r",stdin);
#endif
scanf("%d",&ncase);
while(ncase--)
{
printf("Case %d:\n",++ccase);
scanf("%ld",&N);
build(1,1,N);
for(i=1;i<=N;i++)
{
scanf("%ld",&j);
add(i,j);
}
while(scanf("%s",buf),*buf!='E')
{
scanf("%ld%ld",&i,&j);
if(*buf=='A')
add(i,j);
else if(*buf=='S')
add(i,-j);
else
printf("%ld\n",query(1,i,j));
}
}
return 0;
}
本文通过解决HDU1166敌兵布阵问题,介绍了如何使用段树(segment tree)进行区间更新和查询操作。文章分享了一个具体实现案例,包括构建段树、增加节点值以及查询区间和的方法。
558

被折叠的 条评论
为什么被折叠?



