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. Maven常见知识介绍

    1)pom详解 2)pom详解 3)测试 4)插件与生命周期 5)maven生命周期 6)范围依赖

  2. SQLite基础教程目录

    SQLite基础教程目录 SQLite主页 SQLite概述 SQLite -安装 SQLite -命令 SQLite -语法 SQLite -数据类型 SQLite -创建数据库 SQLite -附 ...

  3. UVALive 3211 Now or Later (2-SAT)

    题目的要求一个最小值最大,二分即可,但是怎么判断呢? 飞机早或者晚两种状态,可以用一个布尔变量表示,假设当前猜测为m,那么根据题意, 如果x和y所对应的时间冲突那么就是¬(xΛy)化成或的形式(¬x) ...

  4. 签名ipa,让其它手机也安装

    开发的时候,需要将app让其它人装上测试,虽然通过xcode可以使用编译进去,但是仍显不方便. 网上有个工具, http://code.google.com/p/iresign/ 通过这个工具,使用自 ...

  5. div+css实现几种经典布局的详解

    一.左右两侧,左侧固定宽度200px,右侧自适应占满 <div class="divBox"> <div class="left">&l ...

  6. webStorm Ctrl+s 自动格式化 然后 保存 用宏命令

    使用WebStorm的Macros宏指令,实现保存的同时格式化代码,并跳至行尾 https://blog.csdn.net/gyz718/article/details/70556188

  7. win10搭建Java环境

    一.下载地址    jdk和jre官方网址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 根据你的系统选择你需要 ...

  8. CPP-基础:windows api 多线程---互斥量、信号量、临界值、事件区别

    http://blog.csdn.net/wangsifu2009/article/details/6728155 四种进程或线程同步互斥的控制方法:1.临界区:通过对多线程的串行化来访问公共资源或一 ...

  9. SSI的实例(登录增删改查)

    源码下载:http://download.csdn.net/detail/u011518709/8195143 主要jar包: 配置文件:web.xml <?xml version=" ...

  10. syslog命令

    更多请关注 Linux命令大全 syslog 介绍 syslog是Linux系统默认的日志守护进程.默认的syslog配置文件是/etc/syslog.conf文件.程序,守护进程和内核提供了访问系统 ...