poj 3468 A Simple Problem with Integers

来源:互联网 发布:latex windows 10 编辑:程序博客网 时间:2024/06/05 01:59

线段树模板题



#include <stdio.h>#define L(t) ((t) << 1)#define R(t) ((t) << 1 | 1)#define MAXN 100010struct SegTree{    int l,r;    long long add, sum;        int getMid(){        return ( l + r) >> 1;    }    int getDis(){        return r - l + 1;    }}       tree[MAXN << 2];int arr[MAXN];void build(int left, int right, int t){           //递归构造    tree[t].l = left;    tree[t].r = right;    tree[t].add = 0;    if(left == right){        tree[t].sum = arr[left];                      //叶结点是数列中的一个数        return;    }    int mid = tree[t].getMid();    build(left, mid, L(t));    build(mid + 1, right, R(t));    tree[t].sum = tree[L(t)].sum + tree[R(t)].sum;          //更新sum}void update(int left, int right, int a, int t){                if( left <= tree[t].l && right >= tree[t].r ){                        tree[t].add += a;            //若当前子树被目标区间覆盖 更新子树的sum和增量(在本次查询中,增量下行到此为之)        tree[t].sum += a * tree[t].getDis();            return;    }    if( tree[t].add ){                //向子结点传递增量,并更新其sum,最后清空自己的增量        tree[L(t)].sum += tree[L(t)].getDis() * tree[t].add;        tree[R(t)].sum += tree[R(t)].getDis() * tree[t].add;        tree[L(t)].add += tree[t].add;        tree[R(t)].add += tree[t].add;        tree[t].add = 0;            }    int mid = tree[t].getMid();    if(right <= mid ){        update(left, right, a, L(t));       //目标区间仅在左子树上    } else if (left > mid ){        update(left, right, a, R(t));           //目标区间仅在右子树上    } else {        update(left, mid, a, L(t));                          //目标区间同时在左右子树上        update(mid + 1, right, a, R(t));    }        tree[t].sum = tree[L(t)].sum + tree[R(t)].sum ;    //更新父结点的sum}long long query(int left, int right, int t){    if(left <= tree[t].l && right >= tree[t].r ){            return tree[t].sum;    }    if( tree[t].add ){               //这一段和update函数一样,是一个pushDown        tree[L(t)].sum += tree[L(t)].getDis() * tree[t].add;        tree[R(t)].sum += tree[R(t)].getDis() * tree[t].add;        tree[L(t)].add += tree[t].add;        tree[R(t)].add += tree[t].add;        tree[t].add = 0;    }    int mid = tree[t].getMid();    if(right <= mid ){        return query(left, right, L(t));        } else if( left > mid ){        return query(left, right, R(t));    }  else {        return query(left, mid ,L(t)) +         query(mid + 1, right, R(t));    }}int main(){    char op[5];    int n, q;    scanf("%d%d",&n, &q);    for(int i = 1; i <= n; ++i){        scanf("%d",&arr[i]);    }    build(1, n, 1);       int a,b,c;    for(int i = 0; i < q; ++i){        scanf("%s ",&op);        if(op[0] == 'Q'){                       scanf("%d %d",&a, &b);            long long sum = query(a, b, 1);            printf("%lld\n",sum);        } else {                       scanf("%d %d %d",&a, &b, &c);            update(a, b, c, 1);        }    }    return 0;}






此题的数组数组解法很巧妙,可见对于前缀和问题树状数组也是很有效的
见   http://kenby.iteye.com/blog/962159


PS:读入数据不要用long long   会WA的。。。被坑了很久



#include<stdio.h>  #define MAXC 100010  long long  C[MAXC], D[MAXC], DQ[MAXC];  int A[MAXC];//////////////////树状数组模板  int lowbit(int t)                {      return t & (t ^ (t - 1));      //计算最小幂  }  int add(int i,long long v,int n)  {  if(n==1)  {    while(i<=MAXC)      //取与C[i]有关的值添上增加的值      {           C[i]+=v;           i+=lowbit(i);      }  return 0; }if(n==2)  {    while(i<=MAXC)          {           D[i]+=v;           i+=lowbit(i);      }  return 0; }if(n==3)  {    while(i<=MAXC)          {           DQ[i]+=v;           i+=lowbit(i);      }  return 0; }return 0;}  long long sum(int i,int n)  {      long long s=0;  if(n==1){    while(i>0)                //取与C[i]有关的值求和      {           s+=C[i];           i-=lowbit(i);      }      return s;  }if(n==2){    while(i>0)                    {           s+=D[i];           i-=lowbit(i);      }      return s;  }if(n==3){    while(i>0)                   {           s+=DQ[i];           i-=lowbit(i);      }      return s;  }return 0;}  //////////////////树状数组模板  int main(){      char op[5];      int n, q;      scanf("%d%d",&n, &q);      for(int i = 1; i <= n; ++i){          scanf("%d",&A[i]);      add(i,A[i],1);    }          int a,b,c;      for(int i = 0; i < q; ++i){          scanf("%s ",&op);            if(op[0] == 'Q'){                           scanf("%d %d",&a, &b);  long long ss =( sum(b,1) + (b+1)*sum(b,2) - sum(b,3) ) - ( sum(a-1,1) + (a)*sum(a-1,2) - sum(a-1,3) );              printf("%lld\n",ss);          } else {                           scanf("%d %d %d",&a, &b, &c);             add(a,c,2);add(b+1,-c,2);add(a,c*a,3);    add(b+1,-c*(b+1),3);        }      }      return 0;  }  






原创粉丝点击