题目链接:(—_—) zZ
题目大意:给出n个点, 现在更新[i...j]区间的每个点的值, 求[k....l]区间的这些点和的值。
code:每回只更新到要更新的区域, 不往下更新, 下回要查询或更新时才往下更新。
#include <stdio.h>
struct node
{
__int64 c, sum;
int l, r;
}tree[100000*4];//c记录当前数量, sum记录l, r要加的数量
int n = 0, m = 0, num[100002];
void add_next(int l, int r, int p)
{
tree[p*2].sum += tree[p].sum;
tree[p*2+1].sum += tree[p].sum;
tree[p*2].c += tree[p].sum*(tree[p*2].r-tree[p*2].l+1);
tree[p*2+1].c += tree[p].sum*(tree[p*2+1].r-tree[p*2+1].l+1);
tree[p].sum = 0;
}
void build_tree(int l, int r, int p)
{
int mid = (l+r)/2;
tree[p].sum = 0;
if(l == r)
{
tree[p].l = tree[p].r = l;
tree[p].c = num[l];
return ;
}
tree[p].l = l; tree[p].r = r;
build_tree(l, mid, p*2);
build_tree(mid+1, r, p*2+1);
tree[p].c = tree[p*2].c+tree[p*2+1].c;
}
void update(int l, int r, int add, int p)
{
int mid = (tree[p].l+tree[p].r)/2;
if(tree[p].l == l && tree[p].r == r)
{
tree[p].c += (r-l+1)*add;
tree[p].sum += add;
return ;
}
if(tree[p].sum)
add_next(l, r, p);
if(l>mid)
update(l, r, add, p*2+1);
else if(r<=mid)
update(l, r, add, p*2);
else
{
update(l, mid, add, p*2);
update(mid+1, r, add, p*2+1);
}
tree[p].c = tree[p*2].c+tree[p*2+1].c;
}
__int64 query(int l, int r, int p)
{
int mid = (tree[p].l+tree[p].r)/2;
if(tree[p].l == l && tree[p].r == r)
return tree[p].c;
if(tree[p].sum)
add_next(l, r, p);
if(l>mid)
return query(l, r, 2*p+1);
else if(r<=mid)
return query(l, r, p*2);
else
return query(l, mid, p*2)+query(mid+1, r, p*2+1);
}
int main()
{
int i = 0, a = 0, b = 0, c = 0;
char ch = 0;
scanf("%d %d", &n, &m);
for(i = 1; i<=n; i++)
scanf("%d", &num[i]);
build_tree(1, n, 1);
while(m--)
{
getchar();
scanf("%c",&ch);
if(ch == 'Q')
{
scanf("%d %d",&a, &b);
printf("%I64d\n", query(a, b, 1));
}
else
{
scanf("%d %d %d",&a, &b, &c);
update(a, b, c, 1);
}
}
return 0;
}
code:树状数组
#include <stdio.h>
#define max 100002
int n = 0, m = 0, A[max];
__int64 ans = 0, B[max], C[max], D[max];
void ADD_B(int i, int c)
{
while(i>0)
{
B[i] += c;
i -= i&(-i);
}
}
void ADD_C(int i, int c)
{
if(i == 0)
return ;
while(i<=n)
{
C[i] += c;
i += i&(-i);
}
}
__int64 SUM_B(int i)
{
__int64 s = 0;
if(i == 0)
return 0;
while(i<=n)
{
s += B[i];
i += i&(-i);
}
return s;
}
__int64 SUM_C(int i)
{
__int64 s = 0;
while(i>0)
{
s += C[i];
i -= i&(-i);
}
return s;
}
__int64 SUM(int x)
{
return SUM_B(x) * x + SUM_C(x - 1);
}
int main()
{
int i = 0, a = 0, b = 0, c = 0;
char ch = 0;
while(scanf("%d %d", &n, &m) != EOF)
{
for(i = 1; i<=n; i++)
scanf("%d", &A[i]);
D[0] = 0;
for(i = 1; i<=n; i++)
D[i] = D[i-1]+A[i];
for(i = 0; i<m; i++)
{
getchar();
scanf("%c",&ch);
if(ch == 'Q')
{
scanf("%d %d", &a, &b);
ans = D[b]-D[a-1];
ans += SUM(b);//得到1到b总共增加了多少
ans -= SUM(a-1);//1到a-1总共增加了多少
printf("%I64d\n", ans);
}
else
{
scanf("%d %d %d", &a, &b, &c);
ADD_B(b, c);
ADD_B(a-1, -c);
ADD_C(b, b*c);
ADD_C(a-1, (a-1)*-c);
}
}
}
return 0;
}
仿造资料2, 原理和资料一是一样的, 只不过实现方式不通
code:
#include <stdio.h>
#define max 100002
int n = 0, m = 0, A[max];
__int64 ans = 0, B[max], C[max], D[max];
void add(int x, __int64 c, __int64 *array)
{
while(x<=n)
{
array[x] += c;
x += x&(-x);
}
}
__int64 sum(int x, __int64 *array)
{
__int64 s = 0;
while(x>0)
{
s += array[x];
x -= x&(-x);
}
return s;
}
int main()
{
int i = 0, a = 0, b = 0, c = 0;
char ch = 0;
while(scanf("%d %d", &n, &m) != EOF)
{
for(i = 1; i<=n; i++)
scanf("%d", &A[i]);
D[0] = 0;
for(i = 1; i<=n; i++)
D[i] = D[i-1]+A[i];
for(i = 0; i<m; i++)
{
getchar();
scanf("%c",&ch);
if(ch == 'Q')
{
scanf("%d %d", &a, &b);
ans = D[b]-D[a-1];
ans += sum(b, B)*b-sum(b, C);
ans -= sum(a-1, B)*(a-1)-sum(a-1, C);
printf("%I64d\n",ans);
}
else
{
scanf("%d %d %d", &a, &b, &c);
add(a, c, B);
add(b+1, -c, B);
add(a, (a-1)*c, C);
add(b+1, (b)*-c, C);
}
}
}
return 0;
}
code:
#include <stdio.h>
#define max 100002
int n = 0, m = 0, A[max];
__int64 ans = 0, B[max], C[max], D[max];
void add(int x, __int64 c, __int64 *array)
{
if(x == 0)
return ;
while(x<=n)
{
array[x] += c;
x += x&(-x);
}
}
__int64 sum(int x, __int64 *array)
{
__int64 s = 0;
while(x>0)
{
s += array[x];
x -= x&(-x);
}
return s;
}
int main()
{
int i = 0, a = 0, b = 0, c = 0;
char ch = 0;
while(scanf("%d %d", &n, &m) != EOF)
{
for(i = 1; i<=n; i++)
scanf("%d", &A[i]);
D[0] = 0;
for(i = 1; i<=n; i++)
D[i] = D[i-1]+A[i];
for(i = 0; i<m; i++)
{
getchar();
scanf("%c",&ch);
if(ch == 'Q')
{
scanf("%d %d", &a, &b);
ans = D[b]-D[a-1];
ans += sum(b, B)*b+sum(b-1, C);
ans -= sum(a-1, B)*(a-1)+sum(a-2, C);
printf("%I64d\n",ans);
}
else
{
scanf("%d %d %d", &a, &b, &c);
add(a, c, B);
add(b+1, -c, B);
add(a-1, (a-1)*-c, C);
add(b, b*c, C);
}
}
}
return 0;
}