您的位置:首页 > 其它

POJ 3468 (线段树 区间增减) A Simple Problem with Integers

2015-04-26 16:30 387 查看
这题WA了好久,一直以为是lld和I64d的问题,后来发现是自己的pushdown函数写错了,说到底还是因为自己对线段树理解得不好。

因为是懒惰标记,所以只有在区间分开的时候才会将标记往下传递。更新和查询都要pushdown。

#include <cstdio>

typedef long long LL;

const int maxn = 100000 + 10;

int n, m, qL, qR, v;
LL sum[maxn << 2], add[maxn << 2];

inline void maintain(int o)
{ sum[o] = sum[o*2] + sum[o*2+1]; }

void build(int o, int L, int R)
{
if(L == R) { scanf("%I64d", &sum[o]); return; }
int M = (L + R) / 2;
build(o*2, L, M);
build(o*2+1, M+1, R);
maintain(o);
}

void pushdown(int o, int L, int R)
{
if(add[o])
{
int lc = o*2, rc = o*2+1;
int M = (L + R) / 2;
add[lc] += add[o];
add[rc] += add[o];
sum[lc] += (LL) add[o] * (M - L + 1);
sum[rc] += (LL) add[o] * (R - M);
add[o] = 0;
}
}

void update(int o, int L, int R)
{
if(qL <= L && qR >= R)
{
add[o] += v;
sum[o] += (LL) v * (R - L + 1);
return;
}
int M = (L + R) / 2;
pushdown(o, L, R);
if(qL <= M) update(o*2, L, M);
if(qR > M) update(o*2+1, M+1, R);
maintain(o);
}

LL query(int o, int L, int R)
{
if(qL <= L && qR >= R) return sum[o];
pushdown(o, L, R);
int M = (L + R) / 2;
LL ans = 0;
if(qL <= M) ans += query(o*2, L, M);
if(qR > M) ans += query(o*2+1, M+1, R);
return ans;
}

int main()
{
//freopen("in.txt", "r", stdin);

scanf("%d%d", &n, &m);
build(1, 1, n);
char op[10];
while(m--)
{
scanf("%s", op);
if(op[0] == 'Q')
{
scanf("%d%d", &qL, &qR);
printf("%I64d\n", query(1, 1, n));
}
else
{
scanf("%d%d%d", &qL, &qR, &v);
update(1, 1, n);
}
}

return 0;
}


代码君
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐