zoukankan      html  css  js  c++  java
  • (线段树、树状数组)poj3468-A Simple Problem with Integers

    You have N integers, A1A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

    Input

    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
    The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of AaAa+1, ... , Ab.

    Output

    You need to answer all Q commands in order. One answer in a line.

    Sample Input

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    

    Sample Output

    4
    55
    9
    15

    Hint

    The sums may exceed the range of 32-bit integers.
     
    依旧是比较基础的成段更新。初始数据的init函数比较好,值得以后借鉴。
     1 #include <iostream>
     2 //#include<bits/stdc++.h>
     3 #include <stack>
     4 #include <queue>
     5 #include <cstdio>
     6 #include <cstring>
     7 #include <algorithm>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef unsigned long long ull;
    11 const int MAX=1e5+5;
    12 struct node
    13 {
    14     int left,right,mid;
    15     ll sum;
    16     ll lazy;
    17 }st[10*MAX];
    18 void pushup(int k)//向上刷新
    19 {
    20     st[k].sum=st[2*k].sum+st[2*k+1].sum;
    21 }
    22 void init(int l,int r,int k)//比较好的初始数据方式
    23 {
    24     st[k].left=l;
    25     st[k].right=r;
    26     st[k].mid=(l+r)/2;
    27     st[k].sum=st[k].lazy=0;
    28     if(l+1==r)
    29         {
    30             scanf("%I64d",&st[k].sum);
    31             return;
    32         }
    33     init(l,(l+r)/2,2*k);
    34     init((l+r)/2,r,2*k+1);
    35     pushup(k);
    36 }
    37 void pushdown(int k)//向下刷新
    38 {
    39     if(st[k].lazy!=0)
    40     {
    41         st[2*k].lazy+=st[k].lazy;
    42         st[2*k+1].lazy+=st[k].lazy;
    43         st[2*k].sum+=(st[2*k].right-st[2*k].left)*st[k].lazy;
    44         st[2*k+1].sum+=(st[2*k+1].right-st[2*k+1].left)*st[k].lazy;
    45         st[k].lazy=0;
    46     }
    47 }
    48 void update(int l,int r,int c,int k)//[l,r]区间加c
    49 {
    50     if(st[k].left>=r||st[k].right<=l)
    51         return;
    52     if(st[k].left>=l&&st[k].right<=r)
    53     {
    54         st[k].sum+=(st[k].right-st[k].left)*c;
    55         st[k].lazy+=c;
    56         return;
    57     }
    58     pushdown(k);
    59     update(l,r,c,2*k);
    60     update(l,r,c,2*k+1);
    61     st[k].sum=st[2*k].sum+st[2*k+1].sum;
    62     return;
    63 }
    64 ll query(int trl,int trr,int ptl,int ptr,int k)//询问[trl,trr]区间和的函数
    65 {
    66     if(ptr<=trl||ptl>=trr)
    67         return 0;
    68     if(ptl+1==ptr||(ptl>=trl&&ptr<=trr))
    69         return st[k].sum;
    70 
    71     pushdown(k);
    72     if(ptl>=trl&&ptr<=trr)
    73         return st[k].sum;
    74     return query(trl,trr,ptl,(ptl+ptr)/2,2*k)+query(trl,trr,(ptl+ptr)/2,ptr,2*k+1);
    75 }
    76 char tem[10];
    77 int main()
    78 {
    79     int n,q;
    80     scanf("%d %d",&n,&q);
    81     init(1,n+1,1);
    82     int i,j,z;
    83     while(q--)
    84     {
    85         scanf("%s %d %d",tem,&i,&j);
    86         if(tem[0]=='Q')
    87             printf("%I64d
    ",query(i,j+1,1,n+1,1));
    88         else
    89         {
    90             scanf("%d",&z);
    91             update(i,j+1,z,1);
    92         }
    93     }
    94 }

     UPD.

    2017.5.22

    学习BIT时再做此题,用线段树重新写了一遍

      1 #include <iostream>
      2 #include <string>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <queue>
      8 #include <set>
      9 #include <map>
     10 #include <list>
     11 #include <vector>
     12 #include <stack>
     13 #define mp make_pair
     14 #define MIN(a,b) (a>b?b:a)
     15 //#define MAX(a,b) (a>b?a:b)
     16 typedef long long ll;
     17 typedef unsigned long long ull;
     18 const int MAX=1e5+5;
     19 const int INF=1e9+5;
     20 const double M=4e18;
     21 using namespace std;
     22 const int MOD=1e9+7;
     23 typedef pair<int,int> pii;
     24 const double eps=0.000000001;
     25 ll lazy[MAX<<2],he[MAX<<2];
     26 char opt[50];
     27 int n,q;
     28 int lo1,lo2,zhi;
     29 void init(int l,int r,int k)
     30 {
     31     if(l==r)
     32     {
     33         lazy[k]=0;
     34         scanf("%lld",&he[k]);
     35         return;
     36     }
     37     int mid=(l+r)/2;
     38     init(l,mid,2*k);
     39     init(mid+1,r,2*k+1);
     40     he[k]=he[2*k]+he[2*k+1];
     41 }
     42 void add(int l,int r,int al,int ar,int k,int num)
     43 {
     44     if(l>=al&&r<=ar)
     45     {
     46 //        he[k]+=(ll)(r-l+1)*num;
     47         lazy[k]+=num;
     48         return;
     49     }
     50     int mid=(l+r)/2;
     51     he[k]+=(ll)(min(r,ar)-max(l,al)+1)*num;
     52     if(ar<=mid)
     53         add(l,mid,al,ar,2*k,num);
     54     else if(al>mid)
     55         add(mid+1,r,al,ar,2*k+1,num);
     56     else
     57     {
     58         add(l,mid,al,ar,2*k,num);
     59         add(mid+1,r,al,ar,2*k+1,num);
     60     }
     61 }
     62 ll query(int l,int r,int ql,int qr,int k)
     63 {
     64     if(r<ql||l>qr)
     65         return 0;
     66     if(l>=ql&&r<=qr)
     67         return he[k]+lazy[k]*(r-l+1);
     68     else
     69     {
     70         int mid=(l+r)/2;
     71         ll re=(min(qr,r)-max(ql,l)+1)*lazy[k];
     72 //        re+=query(l,mid,ql,qr,2*k);
     73 //        re+=query(mid+1,r,ql,qr,2*k+1);
     74         if(qr<=mid)
     75             re+=query(l,mid,ql,qr,2*k);
     76         else if(ql>mid)
     77             re+=query(mid+1,r,ql,qr,2*k+1);
     78         else
     79         {
     80             re+=query(l,mid,ql,qr,2*k);
     81             re+=query(mid+1,r,ql,qr,2*k+1);
     82         }
     83         return re;
     84     }
     85 }
     86 int main()
     87 {
     88     scanf("%d%d",&n,&q);
     89     init(1,n,1);
     90     while(q--)
     91     {
     92         scanf("%s",opt);
     93         if(opt[0]=='Q')
     94         {
     95             scanf("%d%d",&lo1,&lo2);
     96             printf("%lld
    ",query(1,n,lo1,lo2,1));
     97         }
     98         else
     99         {
    100             scanf("%d%d%d",&lo1,&lo2,&zhi);
    101             add(1,n,lo1,lo2,1,zhi);
    102         }
    103     }
    104     return 0;
    105 }

    使用树状数组的做法:

    由于树状数组一般表示”前缀和“含义的量,为了方便表示某一区间的情况,建立两个数组,分别记录add操作(区间更新)加上的值(记为数组lazy),和原本数值之和(记为数组he)。

    add操作[l,r]加a时,lazy数组l位置加上a,r+1位置加上-a。he数组,l位置加上-a(l-1),r位置加上ar即可

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <queue>
     8 #include <set>
     9 #include <map>
    10 #include <list>
    11 #include <vector>
    12 #include <stack>
    13 #define mp make_pair
    14 #define MIN(a,b) (a>b?b:a)
    15 //#define MAX(a,b) (a>b?a:b)
    16 typedef long long ll;
    17 typedef unsigned long long ull;
    18 const int MAX=1e5+5;
    19 const int INF=1e9+5;
    20 const double M=4e18;
    21 using namespace std;
    22 const int MOD=1e9+7;
    23 typedef pair<int,int> pii;
    24 const double eps=0.000000001;
    25 char opt[50];
    26 ll he[MAX],lazy[MAX];
    27 int n,q;
    28 int tem;
    29 int lo1,lo2,zhi;
    30 ll sum(ll *b,int i)
    31 {
    32     ll re=0;
    33     while(i>0)
    34     {
    35         re+=b[i];
    36         i-=i&-i;
    37     }
    38     return re;
    39 }
    40 void add(ll *b,int i,ll val)
    41 {
    42     while(i<=n)
    43     {
    44         b[i]+=val;
    45         i+=i&-i;
    46     }
    47 }
    48 int main()
    49 {
    50     scanf("%d%d",&n,&q);
    51     for(int i=1;i<=n;i++)
    52     {
    53         scanf("%d",&tem);
    54         add(he,i,tem);
    55     }
    56     while(q--)
    57     {
    58         scanf("%s",opt);
    59         if(opt[0]=='C')
    60         {
    61             scanf("%d%d%d",&lo1,&lo2,&zhi);
    62             add(lazy,lo1,zhi);
    63             add(he,lo1,-(ll)(zhi)*(lo1-1));
    64             add(lazy,lo2+1,-zhi);
    65             add(he,lo2+1,(ll)zhi*lo2);
    66         }
    67         else
    68         {
    69             scanf("%d%d",&lo1,&lo2);
    70             ll an=0;
    71             an+=sum(he,lo2)+sum(lazy,lo2)*lo2;
    72             an-=sum(he,lo1-1)+sum(lazy,lo1-1)*(lo1-1);
    73             printf("%lld
    ",an);
    74         }
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    四则运算二
    学习进度
    软件工程个人作业01
    观《构建之法》有感
    软件工程概论课程引言课后作业
    编写一个程序,此程序在运行时要求用户输入一个 整数,代表某门课的考试成绩,程序接着给出“不及格”、“及格”、“中”、“良”、“优”的结论。
    软件需求与分析课堂讨论一
    软件需求模式阅读笔记一
    我们应当怎么做需求分析
    问题账户需求分析
  • 原文地址:https://www.cnblogs.com/quintessence/p/6411341.html
Copyright © 2011-2022 走看看