您的位置:首页 > 其它

poj 3468 A Simple Problem with Integers (线段树 成段更新 加值 求和)

2014-08-07 10:35 393 查看
题目链接

题意:

只有这两种操作

C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

代码风格更新后:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define lson l, mid, 2*rt
#define rson mid+1, r, 2*rt+1
#define LL __int64
const int maxn = 100000+10;
using namespace std;
LL sum[4*maxn], lz[4*maxn];

void pushup(int rt)
{
sum[rt] = sum[2*rt]+sum[2*rt+1];
}
void pushdown(int l, int r, int rt)
{
if(lz[rt]!=0)
{
int mid = (l+r)/2;
sum[2*rt] += lz[rt]*(mid-l+1);
sum[2*rt+1] += lz[rt]*(r-mid);
lz[2*rt] += lz[rt];
lz[2*rt+1] += lz[rt];
lz[rt] = 0;
}
}
void build(int l, int r, int rt)
{
if(l==r)
{
scanf("%I64d", &sum[rt]);
return;
}
int mid = (l+r)/2;
build(lson);
build(rson);
pushup(rt);
}
void update(int ll, int rr, LL c, int l, int r, int rt)
{
if(ll>r) return;
if(rr<l) return;
if(ll<=l && rr>=r)
{
lz[rt] += c;
sum[rt] += (r-l+1)*c;
return;
}
pushdown(l, r, rt);
int mid = (l+r)/2;
update(ll, rr, c, lson);
update(ll, rr, c, rson);
pushup(rt);
}
LL query(int ll, int rr, int l, int r, int rt)
{
if(ll>r) return 0;
if(rr<l) return 0;
if(ll<=l && rr>=r)
return sum[rt];
pushdown(l, r, rt);
int mid = (l+r)/2;
return query(ll, rr, lson)+query(ll, rr, rson);
}
int main()
{
int n, q, a, b;
LL c;
char ch;
while(~scanf("%d%d", &n, &q))
{
memset(sum, 0, sizeof(sum));
memset(lz, 0, sizeof(lz));
build(1, n, 1);
while(q--)
{
getchar();
scanf("%c %d %d", &ch, &a, &b);
if(ch=='Q')
printf("%I64d\n", query(a, b, 1, n, 1));
else
{
scanf("%I64d", &c);
update(a, b, c, 1, n, 1);
}
}
}
return 0;
}


代码风格更新前:

分析:自己写的有点麻烦了,写的时候手残+脑残,改了好久。

val+lazy*(r-l+1)表示和,如果lazy==0表示当前区间加的值不统一。

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define LL __int64
const int maxn = 100000+10;
using namespace std;
int n, q;
__int64 a[maxn];
struct line
{
int l, r;
LL val, lazy;
}tr[4*maxn];

void build(int o, int l, int r)
{
tr[o].l = l; tr[o].r = r;
tr[o].lazy = 0;
if(l==r)
{
tr[o].val = a[l];
return;
}
int mid = (l+r)/2;
build(2*o, l, mid);
build(2*o+1, mid+1, r);
tr[o].val = tr[2*o].val+tr[2*o+1].val;
}
void update(int o, int l, int r, int add)
{
if(tr[o].l==l && tr[o].r==r)
{
tr[o].lazy += add;
return;
}
if(tr[o].lazy)  //之前没向下更新的向下更新
{
tr[2*o].lazy += tr[o].lazy;
tr[2*o+1].lazy += tr[o].lazy;
tr[o].val += (LL)(tr[o].lazy*(tr[o].r-tr[o].l+1));  //同时把lazy存的加到和里
tr[o].lazy = 0;
}
tr[o].val += (LL)(add*(r-l+1)); //在这个过程中把新增加的加上,注意左右区间
int mid = (tr[o].l+tr[o].r)/2;
if(r <= mid) update(2*o, l, r, add);
else if(l > mid) update(2*o+1, l, r, add);
else
{
update(2*o, l, mid, add);
update(2*o+1, mid+1, r, add);
}
}

LL query(int o, int l, int r)
{
if(tr[o].l==l && tr[o].r==r)
return tr[o].val + tr[o].lazy*(r-l+1);
if(tr[o].lazy)  //由于之前可能存在 没有更新的所以向下更新
{
tr[2*o].lazy += tr[o].lazy;
tr[2*o+1].lazy += tr[o].lazy;
tr[o].val += (LL)(tr[o].lazy*(tr[o].r-tr[o].l+1));
tr[o].lazy = 0;
}
int mid = (tr[o].l+tr[o].r)/2;
if(r<=mid) return query(2*o, l, r);
else if(l > mid) return query(2*o+1, l, r);
else
{
return query(2*o, l, mid) + query(2*o+1, mid+1, r);
}
}
int main()
{
int i, l, r, add;
char ch;
while(~scanf("%d%d", &n, &q))
{
for(i = 1; i <= n; i++)
scanf("%I64d", &a[i]);
build(1, 1, n);
for(i = 1; i <= q; i++)
{
getchar();
scanf("%c", &ch);
if(ch=='Q')
{
scanf("%d%d", &l, &r);
printf("%I64d\n", query(1, l, r));
}
else
{
scanf("%d%d%d", &l, &r, &add);
update(1, l, r, add);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐