LOJ #6277. 数列分块入门 1-分块(区间加法、单点查询)

内存限制:256 MiB时间限制:100 ms标准输入输出
题目类型:传统评测方式:文本比较
上传者: hzwer

题目描述

给出一个长为 nn 的数列,以及 nn 个操作,操作涉及区间加法,单点查值。

输入格式

第一行输入一个数字 nn。

第二行输入 nn 个数字,第 ii 个数字为 a_iai,以空格隔开。

接下来输入 nn 行询问,每行输入四个数字 \mathrm{opt}opt、ll、rr、cc,以空格隔开。

若 \mathrm{opt} = 0opt=0,表示将位于 [l, r][l,r] 的之间的数字都加 cc。

若 \mathrm{opt} = 1opt=1,表示询问 a_rar 的值(ll 和 cc 忽略)。

输出格式

对于每次询问,输出一行一个数字表示答案。

样例

样例输入

4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0

样例输出

2
5

数据范围与提示

对于 100\%100% 的数据,1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1n50000,231others、\mathrm{ans} \leq 2^{31}-1ans2311。

 

代码:

 1 //#6277. 数列分块入门 1-区间加法,单点查询
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 typedef long long ll;
 5 const int maxn=5e4+10;
 6 
 7 int n,m,pos[maxn];
 8 int a[maxn],tag[maxn];
 9 
10 void update(int l,int r,int c)
11 {
12     if(pos[l]==pos[r]){//如果在一个块内,直接遍历更新
13         for(int i=l;i<=r;i++)
14             a[i]+=c;
15     }
16     else{//如果不在同一个块内
17         for(int i=l;i<=pos[l]*m;i++)//遍历更新完整块左边的部分
18             a[i]+=c;
19         for(int i=pos[l]+1;i<=pos[r]-1;i++)//更新完整的块
20             tag[i]+=c;
21         for(int i=(pos[r]-1)*m+1;i<=r;i++)//更新完整块右边的部分
22             a[i]+=c;
23     }
24 }
25 
26 int main()
27 {
28     int n;
29     scanf("%d",&n);
30     m=sqrt(n);
31     for(int i=1;i<=n;i++)
32         scanf("%d",&a[i]);
33     for(int i=1;i<=n;i++)
34         pos[i]=(i-1)/m+1;//块号
35     for(int i=1;i<=n;i++){
36         int op,l,r,c;
37         scanf("%d%d%d%d",&op,&l,&r,&c);
38         if(op==0) update(l,r,c);
39         else printf("%d\n",tag[pos[r]]+a[r]);
40     }
41     return 0;
42 }

 

 

posted @ 2019-03-13 19:38  ZERO-  阅读(511)  评论(0编辑  收藏  举报