(线段树、树状数组)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\n",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\n",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\n",an);
74         }
75     }
76     return 0;
77 }

 

posted @ 2017-02-17 19:51  perplex  阅读(208)  评论(0编辑  收藏  举报