线段树用来维护区间,常用来处理与区间相关的问题。
模版题:敌兵布阵
题意:给一个1到n的区间,以及每个点的初始值,然后会再区间上进行操作:修改区间中某一点的值,以及询问一个区间中所有点的和。
思路:用线段树维护整个区间上的值,然后就是单点更新,以及区间求和。
代码:
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
const ll M=50100;
struct N
{
int l,r,v;
int mid()
{
return (l+r)/2;
}
}tree[M<<2];
void build(int rt,int l,int r)
{
tree[rt].l=l;tree[rt].r=r;
if(l==r)
{
scanf("%d",&tree[rt].v);
return ;
}
build(rt*2,l,tree[rt].mid());
build(rt*2+1,tree[rt].mid()+1,r);
tree[rt].v=tree[rt*2].v+tree[rt*2+1].v;
}
void update(int rt,int p,int v)
{
if(tree[rt].l==tree[rt].r)
{
tree[rt].v+=v;
return;
}
if(p<=tree[rt].mid())update(rt*2,p,v);
else update(rt*2+1,p,v);
tree[rt].v=tree[rt*2].v+tree[rt*2+1].v;
}
int query(int rt,int l,int r)
{
if(tree[rt].l==l&&tree[rt].r==r)return tree[rt].v;
if(r<=tree[rt].mid())return query(rt*2,l,r);
else if(l>tree[rt].mid())return query(rt*2+1,l,r);
else return query(rt*2,l,tree[rt].mid())+query(rt*2+1,tree[rt].mid()+1,r);
}
int main()
{
int t,tt=1;
scanf("%d",&t);
while(t--)
{
int n,a,b;
char s[20];
scanf("%d",&n);
build(1,1,n);
printf("Case %d:\n",tt++);
while(scanf("%s",s)==1&&s[0]!='E')
{
if(s[0]=='A')
{
scanf("%d%d",&a,&b);
update(1,a,b);
}
else if(s[0]=='S')
{
scanf("%d%d",&a,&b);
update(1,a,-b);
}
else if(s[0]=='Q')
{
scanf("%d%d",&a,&b);
printf("%d\n",query(1,a,b));
}
}
}
return 0;
}
11万+

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



