POJ3468
Posted 2018slgys
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3468相关的知识,希望对你有一定的参考价值。
POJ3468
题目链接
题目概述
给出一个包含有(N)个元素的数组(a),然后是(m)次操作,操作有以下两种类型:
Q x y
((x leq y))计算(sum_{i = x}^y a[i])C x y d
((x leq y))将区间([x,y])内部的每一个(a[i])加上(d).
对于第一种查询操作输出对应的结果,数据规模:
[1leq N,Mleq 10^5, -10^9 leq A_i leq 10^9, -10^4leq dleq 10^4.
]
题目分析
经典的树状数组区间修改和区间查询的题目,利用初始的前缀和数组和用两个树状数组维持区间修改后的(sum_{i=1}^na[i]).
利用差分转换的原理可以看看这个差分--OIwiki
通过:
[sum_{i=1}^{r+1}(r+1-i+1)cdot f_i - sum_{i=1}^{l}(l-i+1)cdot f_i
]
代码
/*
* @Author: Shuo Yang
* @Date: 2020-08-04 15:46:50
* @LastEditors: Shuo Yang
* @LastEditTime: 2020-08-04 16:58:19
* @FilePath: /Code/POJ/3468.cpp
*/
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
ll t1[N];
ll t2[N];
ll a[N];
int n;
inline int lowbit(int x){
return x & -x;
}
void add(ll* t, int k, int x){
while( k <= n){
t[k] += x;
k += lowbit(k);
}
}
ll sum(ll* t, int k){
ll ans = 0;
while( k > 0){
ans += t[k];
k -= lowbit(k);
}
return ans;
}
void addL(int lef, int rig, int x){
add(t1, lef, x);
add(t2, lef, lef*x);
add(t1, rig+1, -x);
add(t2, rig+1, -(rig+1)*x);
}
int main(int argc, const char** argv) {
int m;
scanf("%d %d",&n,&m);
for(int i = 1; i <=n ; ++i){
scanf("%lld", &a[i]);
a[i] += a[i-1];
}
for(int i = 0; i <m; ++i){
char ch;
int x,y,c;
while( ch != ‘Q‘ && ch !=‘C‘)
scanf("%c",&ch);
// printf("ch=%c**
", ch);
if(ch == ‘Q‘){
scanf("%d %d", &x,&y);
ll ans = (a[y]+(sum(t1,y)*(y+1) - sum(t2,y))) - (a[x-1]+(sum(t1,x)*x-sum(t2,x)));
printf("%lld
", ans);
}else if( ch == ‘C‘){
scanf("%d %d %d",&x,&y,&c);
addL(x,y,c);
}
}
return 0;
}
这里面的树状数组t1
是维护(sum_{i=1}^{n}(n+1)cdot a[i]),t2
数组是维护(sum_{i=1}^{n}icdot a[i]).
区间更新操作是对这两个操作进行的,至于区间求和在原来前缀和的基础上加上这个区间修改后的差分求和得到的就是最终的结果.
(纯粹的板子,但是我说不清楚,┭┮﹏┭┮2333333).
其它
以上是关于POJ3468的主要内容,如果未能解决你的问题,请参考以下文章
POJ-3468-A Simple Problem with integers