POJ_3468

    现在用的方法还是比较慢的,因为YTQ给我那个PPT还没深入研究透,PPT上面对这种的题的解法是用维护前缀和的前缀和以及{n*An}的前缀和来实现的,而我用的方法就是比较朴素的做lazy标记,来标识该区间内每个元素增加了多少。如果需要查询子区间时,再更新子区间的和,并将lazy标记传递下去。

#include<stdio.h>
#include<string.h>
#define MAXD 100010
int N, M, Q;
long long int tree[4 * MAXD], lazy[4 * MAXD], res;
int left[4 * MAXD], right[4 * MAXD], num[4 * MAXD];
char op[5];
void init()
{
int i, j;
for(M = 1; M < N + 2; M <<= 1);
memset(tree, 0, sizeof(tree));
memset(lazy, 0, sizeof(lazy));
for(i = 0, j = M + 1; i < N; i ++, j ++)
scanf("%lld", &tree[j]);
for(i = M, j = 0; i < 2 * M; i ++, j ++)
{
left[i] = right[i] = j;
if(j >= 1 && j <= N)
num[i] = 1;
else
num[i] = 0;
}
for(i = M - 1; i > 0; i --)
{
tree[i] = tree[2 * i] + tree[2 * i + 1];
num[i] = num[2 * i] + num[2 * i + 1];
left[i] = left[2 * i];
right[i] = right[2 * i + 1];
}
}
void add(int cur, int &a, int &b, int &c)
{
int i, k;
if(lazy[cur] && cur < M)
{
lazy[2 * cur] += lazy[cur];
lazy[2 * cur + 1] += lazy[cur];
tree[2 * cur] += lazy[cur] * num[2 * cur];
tree[2 * cur + 1] += lazy[cur] * num[2 * cur + 1];
lazy[cur] = 0;
}
if(left[cur] >= a && right[cur] <= b)
{
k = c * num[cur];
tree[cur] += k;
lazy[cur] = c;
for(i = cur; i ^ 1; i >>= 1)
tree[i >> 1] += k;
return ;
}
if(left[2 * cur] <= b && right[2 * cur] >= a)
add(2 * cur, a, b, c);
if(left[2 * cur + 1] <= b && right[2 * cur + 1] >= a)
add(2 * cur + 1, a, b, c);
}
void make(int cur, int &a, int &b)
{
int i, k;
if(lazy[cur] && cur < M)
{
lazy[2 * cur] += lazy[cur];
lazy[2 * cur + 1] += lazy[cur];
tree[2 * cur] += lazy[cur] * num[2 * cur];
tree[2 * cur + 1] += lazy[cur] * num[2 * cur + 1];
lazy[cur] = 0;
}
if(left[cur] >= a && right[cur] <= b)
{
res += tree[cur];
return ;
}
if(left[2 * cur] <= b && right[2 * cur] >= a)
make(2 * cur, a, b);
if(left[2 * cur + 1] <= b && right[2 * cur + 1] >= a)
make(2 * cur + 1, a, b);
}
void solve()
{
int i, j, a, b, c, s, t;
scanf("%s", op);
if(op[0] == 'C')
{
scanf("%d%d%d", &a, &b, &c);
add(1, a, b, c);
}
else
{
scanf("%d%d", &a, &b);
res = 0;
make(1, a, b);
printf("%lld\n", res);
}
}
int main()
{
while(scanf("%d%d", &N, &Q) == 2)
{
init();
for(int i = 0; i < Q; i ++)
solve();
}
return 0;
}


posted on 2011-11-01 01:09  Staginner  阅读(279)  评论(2编辑  收藏  举报