【树状数组区间修改区间求和】codevs 1082 线段树练习 3
http://codevs.cn/problem/1082/
【AC】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+;
int n;
ll a[maxn];
ll c1[maxn];
ll c2[maxn];
int lowbit(int x)
{
return x&-x;
}
void add(ll *c,int k,ll val)
{
while(k<=n){
c[k]+=val;
k+=lowbit(k);
}
}
ll query(ll *c,int k)
{
ll ans=;
while(k)
{
ans+=c[k];
k-=lowbit(k);
}
return ans;
}
ll solve(int x)
{
ll ans=;
ans+=x*query(c1,x);
ans-=query(c2,x);
return ans;
}
ll solve(int x,int y)
{
return solve(y)-solve(x-);
}
int main()
{
while(~scanf("%d",&n))
{
a[]=;
for(int i=;i<=n;i++)
{
scanf("%I64d",&a[i]);
// cout<<a[i]<<endl;
add(c1,i,a[i]-a[i-]);
add(c2,i,(i-)*(a[i]-a[i-]));
}
int q;
scanf("%d",&q);
int tp;
while(q--)
{
scanf("%d",&tp);
if(tp==)
{
int x,y;ll val;
scanf("%d%d%I64d",&x,&y,&val);
add(c1,x,val);
add(c1,y+,-val);
add(c2,x,1ll*(x-)*val);
add(c2,y+,-1ll*y*val);
}
else
{
int x,y;
scanf("%d%d",&x,&y);
ll ans=solve(x,y);
printf("%I64d\n",ans);
}
}
}
return ;
}
【原理】
原理是用了差分数组,转载自http://www.cnblogs.com/boceng/p/7222751.html
树状数组时间复杂度为O(MlogN), 实际用的时候优于线段树,且写得少。
神牛是引入了差分数组,要维护的差分数组ks[i] = a[i] - a[i-1]; 可以容易得到a[i] = ks[1] + ks[2] + ... + ks[i]; 即前i项和,为方便记为sigma(ks, i),已经可以看到树状数组的影子了,所以求区间和随之得到
a[1] + a[2] + .. + a[n] = sigma(ks, 1) + sigma(ks, 2) + ... + sigma(ks, n);
= n*ks[1] + (n-1)*ks[2] + ... + 2*ks[n-1] + 1*ks[n];
= n*(ks[1] + ks[2] +...+ ks[n]) - (0*ks[1] + 1*ks[2] + ... + (n-1)*ks[n]);
所以可以得到 sum[n] =n * sigma(ks, n) - (0*ks[1] + 1*ks[2] + ... + (n-1)*ks[n]);
令jk[i] = (i-1) * ks[i];
则 sum[n] = n * sigma(ks, n) - sigma(jk, n);
之后便是构造两个树状数组;
int lowbit(int k){
return k & -k;
}
void add(int n, int *c, int k, int va){
while(k <= n){
c[k] += va;
k += lowbit(k);
}
} //------------------------------------- for(i = ; i <= n; ++i){
add(n, c1, i, jk[i]-jk[i-]);
add(n, c2, i, (i-)*(jk[i]-jk[i-]));
}
然后进行查询求和
int sigma(int *c, int k){
int sum = ;
while(k){
sum += c[k];
k -= lowbit(k);
}
return sum;
}
int getSum(int s, int t){
return (t*sigma(c1, t)-sigma(c2, t)) - ((s-)*sigma(c1, s-)-sigma(c2, s-));
}
进行单点查询时,只需两个参数均传入该点。
在进行区间更新的时候,神牛市通过两次维护c1,两次c2得到的,但本人推测了几种情况,都不能很好的解释这么做的原因,
void update(int s, int t, int va){
add(c1, s, va);
add(c1, t+, -va);
add(c2, s, va*(s-));
add(c2, t+, -va*t);
}
【树状数组区间修改区间求和】codevs 1082 线段树练习 3的更多相关文章
- Libre OJ 130、131、132 (树状数组 单点修改、区间查询 -> 区间修改,单点查询 -> 区间修改,区间查询)
这三题均可以用树状数组.分块或线段树来做 #130. 树状数组 1 :单点修改,区间查询 题目链接:https://loj.ac/problem/130 题目描述 这是一道模板题. 给定数列 a[1] ...
- codevs 1082 线段树区间求和
codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- A Simple Problem with Integers 多树状数组分割,区间修改,单点求职。 hdu 4267
A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K ...
- 题解报告:Luogu P3368 【模板】树状数组 2(区间修改,单点查询)
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...
- 主席树套树状数组——带修区间第k大zoj2112
主席树带修第k大 https://www.cnblogs.com/Empress/p/4659824.html 讲的非常好的博客 首先按静态第k大建立起一组权值线段树(主席树) 然后现在要将第i个值从 ...
- P3368 【模板】树状数组 2(区间增减,单点查询)
P3368 [模板]树状数组 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表 ...
- POJ 2155 Matrix【二维树状数组+YY(区间计数)】
题目链接:http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissio ...
- 洛谷 P3368 【模板】树状数组 2(区间加,单点查询)
题目链接 https://www.luogu.org/problemnew/show/P3368 树状数组 最基础的用法:https://www.cnblogs.com/yinyuqin/p/1096 ...
随机推荐
- codevs 2277 爱吃皮蛋的小明(水题日常)
时间限制: 1 s 空间限制: 32000 KB 题目等级 : 白银 Silver 题目描述 Description 小明特别爱吃蛋,特别是皮蛋.他一次可以吃一个蛋或者两个蛋(整个吞下去),而且他 ...
- 文字自动自左向右滚动的js代码
重要的一点,就是scrollLeft一直在变化.对象一直在移动,参照物没有动. 代码: css: #div1{display:black;width:110px;height:50px;line-he ...
- Python学习日志9月16日
刚才我差点睡着了,差资料的时候太费神,有些累. 今天早晨学习了<head first HTML and CSS>,今天把昨天没看了的关于字体和颜色的一章节看完了,真长.我详细的做了笔记,并 ...
- iOS开发资源:推送通知相关开源项目--PushSharp、APNS-PHP以及Pyapns等
PushSharp (github) PushSharp是一个实现了由服务器端向移动客户端推送消息的开源C#库,支持 iOS (iPhone/iPad APNS). Android (C2DM/GC ...
- CPP-基础:关于多态
类的多态特性是支持面向对象的语言最主要的特性,有过非面向对象语言开发经历的人,通常对这一章节的内容会觉得不习惯,因为很多人错误的认为,支持类的封装的语言就是支持面向对象的,其实不然,Visua ...
- JS中鼠标左右键以及中键的事件
在三维场景中有时候需要判断鼠标的事件,除了使用的click事件,只有鼠标左键有效,而右键无效.而对于onmousedown.onmouseup的时候鼠标的事件左键/右键有效.详细请看w3c上的资料. ...
- jsTree展开根节点 设置用户图标
$("#jstree").on("loaded.jstree", function (event, data) { var n = 0; var root = ...
- Linux C++/C开发所必需的一系列工具
系统平台下的开发工具.开发环境各有不同.Linux C++/C开发所必需的一系列工具: 1. vi(vim)文本编辑器一个UNIX世界标准的文本编辑器,简约而强大,不论作为开发人员还是系统管理员,熟练 ...
- vue 点击倒计时 ajax 封装
方法:function(){ var that = this; if (that.time == 0) { that.disabled = false; that.text ="点击获取&q ...
- JS添加验证页面中script标签中是否存在jquery文件
window.onload = function() { var al = document.getElementsByTagName("script"); var new_ele ...