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的更多相关文章

  1. Libre OJ 130、131、132 (树状数组 单点修改、区间查询 -> 区间修改,单点查询 -> 区间修改,区间查询)

    这三题均可以用树状数组.分块或线段树来做 #130. 树状数组 1 :单点修改,区间查询 题目链接:https://loj.ac/problem/130 题目描述 这是一道模板题. 给定数列 a[1] ...

  2. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  3. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  4. A Simple Problem with Integers 多树状数组分割,区间修改,单点求职。 hdu 4267

    A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  5. 题解报告:Luogu P3368 【模板】树状数组 2(区间修改,单点查询)

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  6. 主席树套树状数组——带修区间第k大zoj2112

    主席树带修第k大 https://www.cnblogs.com/Empress/p/4659824.html 讲的非常好的博客 首先按静态第k大建立起一组权值线段树(主席树) 然后现在要将第i个值从 ...

  7. P3368 【模板】树状数组 2(区间增减,单点查询)

    P3368 [模板]树状数组 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表 ...

  8. POJ 2155 Matrix【二维树状数组+YY(区间计数)】

    题目链接:http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissio ...

  9. 洛谷 P3368 【模板】树状数组 2(区间加,单点查询)

    题目链接 https://www.luogu.org/problemnew/show/P3368 树状数组 最基础的用法:https://www.cnblogs.com/yinyuqin/p/1096 ...

随机推荐

  1. Java静态方法不能被覆盖

    // 静态方法不能被覆盖   /*class Super{     static String name(){         return "mother";     } }   ...

  2. Spring Boot :Druid Monitor

    忙里偷个闲,在这里分享一下SpringBoot集成Druid实现数据库监控功能,有什么错误欢迎大家指出! 参考文件: Spring实现Druid监控:https://www.cnblogs.com/w ...

  3. js 双向绑定

    //双向绑定实例 <input name="" ng-bind-123="name" /> function DataBinder( object_ ...

  4. Python 元组、字典、集合操作总结

    元组 a=('a',) a=('a','b') 特点 有序 不可变,不可以修改元组的值,无法为元组增加或者删除元素 元组的创建 a=('a',) a=('a','b') tuple('abcd') 转 ...

  5. CAD交互绘制mcdbsolid对象(网页版)

    主要用到函数说明: _DMxDrawX::DrawSolid 绘McDbSolid对象.详细说明如下: 参数 说明 DOUBLE dX1 第一个点X DOUBLE dY1 第一个点Y DOUBLE d ...

  6. 后台返回平铺数据,如何转换成树形json并渲染树形结构,ant tree 异步加载

    如何后台返回对象数组(平铺式) 1.根据字段标识(板块)获取根节点 ### initTreeData(dataOrg){ var resultArr=dataOrg[0] var secArr=[]; ...

  7. JavaScript中数据类型和typeof返回的数据类型

    除了上图,要注意三点:1.symbol是ES6中新增的数据类型 2.typeof(null)结果是Object 3.typeof(Object)和typeof(Array)的结果是function,因 ...

  8. Bootstrap历练实例:垂直的按钮组

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  9. 【倍增】7.11fusion

    非常奇妙的倍增题 题目描述 知名科学家小A在2118年在计算机上实现了模拟聚变的过程.我们将她研究的过程简化.核子共有26种,可以用a到z共26个字母表示.核子聚变的过程可以用一个字符串描述.按照顺序 ...

  10. PHP调用新浪API 生成短链接

    我们经常收到类似于这样的短信(如下图),发现其中的链接并不是常规的网址链接,而是个短小精悍的短链接,产品中经常需要这样的需求,如果在给用户下发的短信中是一个很长的连接,用户体验肯定很差,因此我们需要实 ...