线段树练习 codevs 1080
/* codevs 1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 一行N个方格,开始每个格子里都有一个整数。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N<100000,,提问和修改的总数m<10000条。 输入描述 Input Description 输入文件第一行为一个整数N,接下来是n行n个整数,表示格子中原来的整数。接下一个正整数m,再接下来有m行,表示m个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求[a,b]之间的区间和。 输出描述 Output Description 共m行,每个整数 样例输入 Sample Input 6 4 5 6 2 1 3 4 1 3 5 2 1 4 1 1 9 2 2 6 样例输出 Sample Output 22 22 数据范围及提示 Data Size & Hint 1≤N≤100000, m≤10000 。 */ #include<cstdio> int tot=0; const int maxn=100010; int a[100010]={0}; struct treetype { int left,right; int lptr,rptr; int sum; }t[2*maxn]; void buildtree(int ll,int rr) { int cur=++tot; t[cur].left=ll; t[cur].right=rr; if (ll!=rr-1) { t[cur].lptr=tot+1; buildtree(ll,(ll+rr)/2); t[cur].rptr=tot+1; buildtree((ll+rr)/2,rr); t[cur].sum=t[t[cur].lptr].sum+t[t[cur].rptr].sum; } else t[cur].sum=a[ll]; } void change(int k,int p,int tb) { if (t[k].left==t[k].right-1) t[k].sum+=tb; else { if (p<(t[k].left+t[k].right)/2) change(t[k].lptr,p,tb); if (p>=(t[k].left+t[k].right)/2) change(t[k].rptr,p,tb); t[k].sum=t[t[k].lptr].sum+t[t[k].rptr].sum; } } int qwer(int k,int p,int tb) { if (p<=t[k].left&&tb>=t[k].right) return t[k].sum; int ans=0; if (p<(t[k].left+t[k].right)/2) ans+=qwer(t[k].lptr,p,tb); if (tb>(t[k].left+t[k].right)/2) ans+=qwer(t[k].rptr,p,tb); return ans; } int main() { int n,m,at,p,k; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); buildtree(1,n+1); scanf("%d",&m); for (int i=1;i<=m;i++) { scanf("%d%d%d",&at,&p,&k); if (at==1) change(1,p,k); if (at==2) printf("%d\n",qwer(1,p,k+1)); } return 0; }