[Codevs] 1082 线段树练习3

1082 线段树练习 3

 时间限制: 3 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
题目描述 Description

给你N个数,有两种操作:


1:给区间[a,b]的所有数增加X

2:询问区间[a,b]的数的和。

 

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数, 

再接下来一个正整数Q,每行表示操作的个数,

如果第一个数是1,后接3个正整数,

表示在区间[a,b]内每个数增加X,如果是2,

表示操作2询问区间[a,b]的和是多少。 

pascal选手请不要使用readln读入

 
输出描述 Output Description

对于每个询问输出一行一个答案

 
样例输入 Sample Input

3

1 2 3 

2

1 2 3 2

2 2 3

 
样例输出 Sample Output

9

 
数据范围及提示 Data Size & Hint

数据范围

1<=n<=200000

1<=q<=200000

 

分析 Analysis

分块!

分块除了细节难调外没有什么问题,,,只要理解到位并且有自己的码风即可。

更具体的分析:

[Codevs] 1081 线段树练习 2 ----“分块!”

 

代码 Code

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #define maxn 1000000
 5 using namespace std;
 6 
 7 long long block[maxn],size,sum[maxn],add[maxn],arr[maxn],n,q,swi;
 8 
 9 void modify(){
10     long long a,b,c;
11     scanf("%lld%lld%lld",&a,&b,&c);
12     a--,b--;
13     
14     for(long long i = a;i <= min(block[a]*size-1,b);i++)
15         arr[i] += c,sum[block[i]] += c;
16     if(block[a] != block[b]){
17         for(long long i = (block[b]-1)*size;i <= b;i++)
18             arr[i] += c;
19         sum[block[b]] += (b-(block[b]-1)*size+1)*c;
20     }for(long long i = block[a]+1;i < block[b];i++)
21         sum[i] += size*c,add[i] += c;
22 }
23 
24 void query(){
25     long long a,b;
26     scanf("%lld%lld",&a,&b);
27     a--,b--;
28     long long ans = 0;
29     
30     for(long long i = a;i <= min(block[a]*size-1,b);i++)
31         ans += arr[i]+add[block[i]];
32     if(block[a] != block[b]){
33         for(long long i = (block[b]-1)*size;i <= b;i++)
34             ans += arr[i]+add[block[i]];
35     }for(long long i = block[a]+1;i < block[b];i++)
36         ans += sum[i];
37         
38     printf("%lld\n",ans);
39 }
40 
41 int main(){
42     scanf("%lld",&n);
43     size = (long long)sqrt(n)+1;
44     for(long long i = 0;i < n;i++) block[i] = i/size+1;
45     for(long long i = 0;i < n;i++) scanf("%lld",&arr[i]);
46     for(long long i = 0;i < n;i++) sum[block[i]] += arr[i];
47     
48     scanf("%lld",&q);
49     for(long long i = 0;i < q;i++){
50         scanf("%lld",&swi);
51         if(swi%2) modify();
52         else query();
53     }
54     
55     return 0;
56 }
分块!

 

posted @ 2017-09-12 21:49  μSsia  阅读(114)  评论(0编辑  收藏  举报