LOJ #6280. 数列分块入门 4-分块(区间加法、区间求和)

内存限制:256 MiB时间限制:500 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,表示询问位于 [l, r][l,r] 的所有数字的和 \bmod (c+1)mod(c+1)。

输出格式

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

样例
样例输入
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4
样例输出
1
4
数据范围与提示

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

 

代码;

 1 //#6280. 数列分块入门 4-区间加法,区间求和
 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 ll a[maxn],b[maxn],tag[maxn];
 9 
10 void update(int l,int r,ll c)
11 {
12     for(int i=l;i<=min(pos[l]*m,r);i++){
13         a[i]+=c;
14         b[pos[l]]+=c;
15     }
16     if(pos[l]!=pos[r]){
17         for(int i=(pos[r]-1)*m+1;i<=r;i++){
18             a[i]+=c;
19             b[pos[r]]+=c;
20         }
21     }
22     for(int i=pos[l]+1;i<pos[r];i++){
23         tag[i]+=c;
24     }
25 }
26 
27 ll query(int l,int r)
28 {
29     ll ans=0;
30     for(int i=l;i<=min(pos[l]*m,r);i++){
31         ans+=a[i]+tag[pos[l]];
32     }
33     if(pos[l]!=pos[r]){
34         for(int i=(pos[r]-1)*m+1;i<=r;i++){
35             ans+=a[i]+tag[pos[r]];
36         }
37     }
38     for(int i=pos[l]+1;i<pos[r];i++){
39         ans+=b[i]+tag[i]*m;
40     }
41     return ans;
42 }
43 
44 int main()
45 {
46     scanf("%d",&n);
47     m=sqrt(n);
48     for(int i=1;i<=n;i++){
49         scanf("%d",&a[i]);
50         b[i]=a[i];
51         pos[i]=(i-1)/m+1;
52     }
53     for(int i=1;i<=m+1;i++){
54         int cnt=0;
55         for(int j=(i-1)*m+1;j<=min(i*m,n);j++){
56             cnt+=a[j];
57         }
58         b[i]=cnt;
59     }
60     for(int i=1;i<=n;i++){
61         int op,l,r;
62         ll c;
63         scanf("%d%d%d%lld",&op,&l,&r,&c);
64         if(op==0){
65             update(l,r,c);
66         }
67         else{
68             printf("%lld\n",query(l,r)%(c+1));
69         }
70     }
71 }
72 
73 
74 /*
75 10
76 1 3 4 2 5 7 11 3 5 1
77 0 1 5 1
78 1 1 7 2
79 0 3 9 1
80 1 4 8 7
81 1 1 10 6
82 1 3 5 3
83 1 5 10 7
84 1 6 10 6
85 1 2 7 4
86 1 2 7 5
87 
88 2
89 3
90 5
91 1
92 6
93 3
94 1
95 5
96 */

 

 

 

转载于:https://www.cnblogs.com/ZERO-/p/10525669.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值