您的位置:首页 > 其它

线段树专辑——hdu 1166 敌兵布阵

2011-11-09 10:41 375 查看
http://acm.hdu.edu.cn/showproblem.php?pid=1166

这是一道线段树的基础入门题,题目中的所有跟新操作都是对点进行的,也即无需任何lazy标记传递信息。由于是对点进行的操作,我们在建树的时候应该将数建成点树,即 build(2*i,l,mid); build(2*i+1,mid+1,r); 后面将会有需要段树的题目,待续。 这题唯一的技巧应该就是查找了,我们在对某点进行跟新之后,可以采用之下而上的DP方式,跟新每一段中的人数信息,这样就可以为查找节约很多时间

View Code

#include<iostream>
#include<string>
using namespace std;

struct node
{
int l;
int r;
int sum;
};

node tree[250000];
int n;
int num[50001];

void build(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
if(l==r)
{
tree[i].sum=num[l];
return;
}
int mid=(l+r)/2;
build(2*i,l,mid);
build(2*i+1,mid+1,r);
tree[i].sum=tree[2*i].sum+tree[2*i+1].sum;  //从下向上返回跟新,为查找节约时间
}

void updata(int i,int l,int r,int w)
{
if(tree[i].l>r || tree[i].r<l)
return;
if(tree[i].l>=l && tree[i].r<=r)
{
tree[i].sum+=w;
return;
}
updata(2*i,l,r,w);
updata(2*i+1,l,r,w);
tree[i].sum=tree[2*i].sum+tree[2*i+1].sum; //从下向上返回跟新,为查找节约时间
}

int ans;
void find(int i,int l,int r)
{
if(tree[i].l>r || tree[i].r<l)
return;
if(tree[i].l>=l && tree[i].r<=r)
{
ans+=tree[i].sum;
return;
}
find(2*i,l,r);
find(2*i+1,l,r);
}

int main()
{
int cas,i,a,b,o=1;
char str[10];
freopen("in.txt","r",stdin);
scanf("%d",&cas);
while(cas--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
build(1,1,n);
printf("Case %d:\n",o++);
while(1)
{
scanf("%s",str);
if(str[0]=='E')
break;
scanf("%d%d",&a,&b);
if(str[0]=='S')
{
updata(1,a,a,-b);
}
else if(str[0]=='A')
{
updata(1,a,a,b);
}
else
{
ans=0;
find(1,a,b);
printf("%d\n",ans);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: