POJ3468 A Simple Problem with Integers

来源:互联网 发布:块语言编程游戏迷宫 编辑:程序博客网 时间:2024/06/13 12:18

一.原题链接: http://poj.org/problem?id=3468

二.题目大意:给出1到N个数,2种操作,Q a b查询从第a个数到第b个数的总和,C a b c从第a个数到第b个数每个数加上c。对于每次查询,输出总和。

三.思路:线段树成段更新模板题。所谓成段更新,就是加一个lazy标记,缓存要增加的元素,每次更新不更新到底,而是累积到lazy数组中,原题为add数组。要进行更深的查询或者更深的更新,用pushDown向下更新,这样就可以避免不必要的更新。

四.代码

#include <cstdio>#include <cmath> using namespace std; const int MAX_N = 100100;const int INF = 0x3f3f3f3f; #define LC(t) t<<1#define RC(t) t<<1|1 struct node{    int l, r;    int mid()    {        return l+r >> 1;    }}seTree[4*MAX_N]; long long add[MAX_N<<2],sum[MAX_N<<2]; void build(int nd, int l, int r){    seTree[nd].l = l;    seTree[nd].r = r;    sum[nd] = add[nd] = 0;    if(l == r)        return;    int mid = seTree[nd].mid();    build(LC(nd), l, mid);    build(RC(nd), mid+1, r);} void pushDown(int nd, int len){    if(!add[nd])        return;    add[LC(nd)] += add[nd];    add[RC(nd)] += add[nd];    sum[LC(nd)] += add[nd]*(len -(len>>1));    sum[RC(nd)] += add[nd]*(len>>1);    add[nd] = 0;} void pushUp(int nd){    sum[nd] = sum[LC(nd)] + sum[RC(nd)];} void upDate(int nd, int l, int r,int ele){    if(l == seTree[nd].l && r ==seTree[nd].r){        sum[nd] += ele*(r-l+1);        add[nd] += ele;        return;    }     if(seTree[nd].l == seTree[nd].r)        return;    pushDown(nd, seTree[nd].r-seTree[nd].l+1);    int mid = seTree[nd].mid();     if(r <= mid)        upDate(LC(nd), l, r, ele);    else if(l > mid)        upDate(RC(nd), l, r, ele);    else{        upDate(LC(nd), l, mid, ele);        upDate(RC(nd), mid+1, r, ele);    }    pushUp(nd);} long long query(int nd, int l,int r){    if(seTree[nd].l == l &&seTree[nd].r == r)        return sum[nd];     pushDown(nd, seTree[nd].r-seTree[nd].l+1);    int mid = seTree[nd].mid();     if(r <= mid)        return query(LC(nd), l, r);    if(l > mid)        return query(RC(nd), l, r);    return query(LC(nd), l, mid) +query(RC(nd), mid+1, r);} int main(){    //freopen("in.txt","r", stdin);     int N, Q, i, ele, a, b, c;    char ch;     while(~scanf("%d%d", &N,&Q)){        build(1, 1, N);         for(i = 1; i <= N; i++){            scanf("%d", &ele);            upDate(1, i, i, ele);        }         for(i = 1; i <= Q; i++){            scanf("\n%c %d %d",&ch, &a, &b);            if(ch == 'C'){                scanf("%d", &c);                upDate(1, a, b, c);            }            else                printf("%I64d\n",query(1, a, b));        }    }    return 0;}


五. 易错点:本渣还是弄了好久,一开始混淆了线段树的左右边界和要查询和更新的左右边界,然后还犯了奇数整除会损失精度的错误,也就是说len-len/2与len/2是不一样的。

 

0 0