POJ3468 A Simple Problem with Integers

1|0A Simple Problem with Integers

题目链接:A Simple Problem with Integers

1|1题意

给定N个数,可以选择[l,r],让下标在区间内的值都增加一定值,或者输出下标在区间内元素的和。

1|2思路

可以用带懒标记的线段树写,但是代码太长,不利于编写。这里有一个利用差分借助树状数组实现的写法,非常巧妙,可以实现区间修改(受限于差分的性质,不能实现区间赋值,只能区间加值),区间查询。

令原数组为a[],差分数组为c[],令b[i]=(i1)c[i]则:

i=1na[i]=c[1]+(c[1]+c[2])+...+(c[1]+c[2]+...+c[n1]+c[n])=i=1n(ni+1)c[i]

在这一步,(ni+1)c[i]不能直接用树状数组操作,因为式子中的n不是题目中的n,而是每次查询时使用的,导致这个式子在add时无法操作,还需要进一步转化:

i=1n(ni+1)c[i]=ni=1nc[i]i=1n(i1)c[i]=ni=1nc[i]i=1nb[i]

这样就可以利用c[i]b[i]创建两个树状数组来对区间操作。

1|3代码

#include <cstdio> #include <iostream> using namespace std; #define LL long long const int maxn = 1e5 + 5; int a[maxn], n; LL b[maxn], c[maxn]; int lowbit(int x) { return x & -x; } void add(int x, LL d) { LL tmp = x; while (x <= n) { c[x] += d; b[x] += (tmp - 1) * d; x += lowbit(x); } } LL query(int x) { LL sum = 0, tmp = x; while (x > 0) { sum += tmp * c[x] - b[x]; x -= lowbit(x); } return sum; } void sol() { int q; cin >> n >> q; for (int i = 1; i <= n; ++i) { cin >> a[i]; add(i, a[i] - a[i - 1]); } for (int i = 1; i <= q; ++i) { char op; getchar(); cin >> op; int x, y; cin >> x >> y; if (op == 'Q') cout << query(y) - query(x - 1) << endl; else { int d; cin >> d; add(x, d); add(y + 1, -d); } } } int main() { sol(); return 0; }

__EOF__

本文作者FlyingLight
本文链接https://www.cnblogs.com/FlyingLight/p/17546786.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FlyingLight  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示