P3368 【模板】树状数组 2(区间增减,单点查询)

 P3368 【模板】树状数组 2

题目描述

如题,已知一个数列,你需要进行下面两种操作:

1.将某区间每一个数数加上x

2.求出某一个数的和

输入输出格式

输入格式:

第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含2或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

操作2: 格式:2 x 含义:输出第x个数的值

输出格式:

输出包含若干行整数,即为所有操作2的结果。

输入输出样例

输入样例#1:
5 5
1 5 4 2 3
1 2 4 2
2 3
1 1 5 -1
1 3 5 7
2 4
输出样例#1:
6
10

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=10000,M<=10000

对于100%的数据:N<=500000,M<=500000

样例说明:

故输出结果为6、10

 1 #include<iostream>
 2 using namespace std;
 3 
 4 const int N = 500100 ;
 5 
 6 int n,m,a;
 7 int ch,x,y,v;
 8 int sum[N];//树状数组 
 9 
10 int lowbit(int x)         
11 {
12     return x&(-x);
13 }
14 
15 void update(int p,int v)    //将第P个数增加v 
16 {
17     while(p<=n)
18     {
19         sum[p] += v;
20         p += lowbit(p);
21     }    
22 } 
23 
24 int query(int p)    //查询第p个点的值是多少 
25 {
26     int ans=0;
27     while(p)
28     {
29         ans += sum[p];
30         p -= lowbit(p);
31     }
32     return ans;
33 }
34 
35 int main()
36 {
37     ios::sync_with_stdio(false) ; 
38     cin>>n>>m;
39     int last=0;
40     for (int i=1;i<=n;i++) 
41     {
42         cin>>a;
43         update(i,a-last);  //建树 
44         last = a;
45     /*    
46         这里运用了差分思想,假设原本的数据存在a数组中,
47         那么c数组储存的就是c[i]=a[i]-a[i-1],如果c[1]=a[1],那么很明显
48         a[i]=c[i]+c[i-1]+c[i-2]+...+c[2]+c[1].
49         这样我们每次单点查询的时候只要加上c数组的前缀就可以了。
50     */
51     }
52     for (int i=1;i<=m;++i) 
53     {
54         cin>>ch;
55         if (ch==1)        //区间修改 
56         {
57             cin>>x>>y>>v;
58             update(x,v);
59               update(y+1,-v); 
60         }
61         if (ch==2)        //单点查询 
62         {
63             cin>>x;            
64             cout<<query(x)<<endl; 
65         }
66     }
67     return 0;
68 }

更新模板

 1 #include<cstdio>
 2 int sum[500100];
 3 int n,m,last = 0;
 4 
 5 void update(int p,int v) {
 6     for (; p<=n; p+=p&(-p)) sum[p] += v;
 7 }
 8 int query(int p) {
 9     int ans = 0;
10     for (; p; p-=p&(-p)) ans += sum[p];
11     return ans;
12 }
13 
14 int main()
15 {
16     scanf("%d%d",&n,&m);
17     for (int a,i=1; i<=n; ++i)
18     {
19         scanf("%d",&a);
20         update(i,a-last);
21         last = a;
22     }
23     for (int x,y,z,a,i=1; i<=m; ++i)
24     {
25         scanf("%d",&a);
26         if (a==1)    //区间修改
27         {
28             scanf("%d%d%d",&x,&y,&z);
29             update(x,z);
30             update(y+1,-z); 
31         } 
32         else        //单点查询 
33         {
34             scanf("%d",&x);
35             printf("%d
",query(x));
36         }
37     }
38     return 0;
39 }
原文地址:https://www.cnblogs.com/mjtcn/p/6831402.html