线段树练习五
题目链接
Description
一行N个方格,开始每个格子里的数都是0。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N≤100000,提问和修改的总数可能达到100000条。
Input
20 //方格个数
6 //有几组操作
M 1 1 //表示修改,第一个表示格子位置,第二个数表示在原来的基础上加上的数,
M 2 2
M 3 4
M 3 -5
M 6 7
C 2 6 //表示统计 ,第一个数表示起始位置,第二个数表示结束位置
Output
8
思路
更新的时候,先更新最低端,然后出栈的时候根据两个儿子的值更新父亲的值;
统计就正常统计;
代码
#include<cstdio>
#include<iostream>
using namespace std;
struct str{
int l,r,v;
}t[300001];
int n,m,x,y,ans,mm;
char c;
void bui(int k,int a,int b)//建树
{
mm=max(k,mm);
t[k].l=a;
t[k].r=b;
if(a==b)
return;
int mid=(a+b)/2;
bui(k*2,a,mid);
bui(k*2+1,mid+1,b);
}
void ins(int k,int a,int num)
{
if(t[k].l==a&&t[k].r==a)//到达要修改的点
{
t[k].v+=num;
return;
}
if(a<=t[k*2].r)//要修改的点在左边
ins(k*2,a,num);
else//要修改的点在右边
ins(k*2+1,a,num);
t[k].v=t[k*2].v+t[k*2+1].v;//出栈前根据儿子的值更新父亲的值
}
int que(int k,int a,int b)
{
if(t[k].l==a&&t[k].r==b)//到达要统计的点
return t[k].v;
else if(b<=t[k*2].r)//要统计的点在左边
return que(k*2,a,b);
else if(t[k*2+1].l<=a)//要统计的点在右边
return que(k*2+1,a,b);
else//要统计的点跨越左右两边
return que(k*2,a,t[k*2].r)+que(k*2+1,t[k*2+1].l,b);
}
int main()
{
scanf("%d%d",&n,&m);
bui(1,1,n);
for(int i=1;i<=m;i++)
{
cin>>c;
scanf("%d%d",&x,&y);
if(c=='M')
ins(1,x,y);
else if(c=='C')
{
ans=que(1,x,y);
printf("%d\n",ans);
}
}
return 0;
}