——我大C++的指针岂是尔等能够简单领悟!
题意
- 给N个节点,标号A1~An,然后有Q个操作,操作分为Q i j,查询i,j间的区间和。C i j k,i到j个数字,每个数字增加k,并且输出。
输入输出分析
给N,Q,然后跟操作。注意判断Q,C使用scanf("%s")。
测试数据:
Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
Sample Output
4
55
9
15
算法数据结构分析
线段树基础题目,但是在其上添加了区间加和操作,增加了难度。 如果每个节点直接更新肯定是不行的,可以保存sum,inc(增量)来进行计算。 如果区间正好对应,那么将this.inc += inc。如果区间不是直接对应的,那么sum值增加inc×增加的个数。 之后在进行查询的同时,如果inc的值不是0,可以代入到下一层的inc中,本sum += inc×节点个数。
AC代码:
处理指针的时候出现了些问题,没有写L == R的情况溢出。还有就是r <= mid的情况也没有留意,也造成溢出问题。
最后的问题就是sum一开始忘记inc×个数,直接导致多次WA。
还有就是i从1开始,树状数组也是。
//author: svtter
//
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <map>
#include <algorithm>
#include <queue>
#include <cmath>
#define INF 0xffffff
#define lln long long
#ifdef ONLINE_JUDGE
#define FOI(file) 0
#define FOW(file) 0
#else
#define FOI(file) freopen(file,"r",stdin);
#define FOW(file) freopen(file,"w",stdout);
#endif
using namespace std;
struct CNode
{
int L, R;
CNode *pLeft, *pRight;
lln sum;
lln inc;
int mid()
{
return (L+R)/2;
}
};
#define N 300000
CNode tree[N];
int c = 0;
void BuildTree(CNode *root, int l, int r)
{
root->L = l;
root->R = r;
root->sum = 0;
root->inc = 0;
//没写
if(l == r)
return;
c ++;
root->pLeft = tree+c;
c ++;
root->pRight = tree+c;
if(l != r)
{
BuildTree(root->pLeft, l, (l+r)/2);
BuildTree(root->pRight,(l+r)/2+1, r);
}
}
void Insert(CNode *root, int i, int val)
{
if(root->L == root->R)
{
root->sum = val;
return;
}
root->sum += val;
if(i <= root->mid())
Insert(root->pLeft, i, val);
else
Insert(root->pRight, i, val);
}
void Add(CNode *root, int l, int r, lln inc)
{
if(root->L == l && root->R == r)
{
root->inc += inc;
return;
}
root->sum += inc *(r-l+1);
if(r <= root->mid())
Add(root->pLeft, l, r, inc);
else if(l > root->mid())
Add(root->pRight, l, r, inc);
else
{
Add(root->pLeft, l, root->mid(), inc);
Add(root->pRight, root->mid()+1, r, inc);
}
}
lln Query(CNode *root, int l, int r, lln inc)
{
if(root->L == l && root->R == r)
return root->sum + (root->inc+inc) * (r-l+1);
if(r <= root->mid())
return Query(root->pLeft, l, r, root->inc+inc);
else if(l > root->mid())
return Query(root->pRight,l, r, root->inc+inc);
else
{
return Query(root->pLeft, l, root->mid(), root->inc+inc) +
Query(root->pRight, root->mid()+1, r, root->inc+inc);
}
}
int main()
{
FOI("input");
//FOW("output");
//write your programme here
int n, q, m;
int i, j, k;
int t;
char ch[10];
lln ans;
CNode *root;
scanf("%d%d", &n ,&q);
root = tree;
c = 0;
BuildTree(root, 1, n);
for(i = 1; i <=n ;i++)
{
scanf("%d", &t);
Insert(root, i, t);
}
for(i = 0; i < q; i++)
{
scanf("%s", ch);
if(ch[0] == 'Q')
{
scanf("%d%d", &j, &k);
ans = Query(root, j, k, 0);
printf("%lld\n", ans);
}
else
{
scanf("%d%d%d", &j, &k, &m);
Add(root, j, k, m);
}
}
return 0;
}