You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15 区间修改 区间查询 注意pushdown的操作就可以了
 #include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
using namespace std;
#define FO freopen("in.txt","r",stdin);
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define debug(x) cout << "&&" << x << "&&" << endl;
#define lowbit(x) (x&-x)
#define mem(a,b) memset(a, b, sizeof(a));
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=;
const int inf = 0x3f3f3f3f;
ll powmod(ll a,ll b) {ll res=;a%=mod;for(;b;b>>=){if(b&)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
//head //区间修改 区间查询
const int maxx=;
ll sum[maxx<<],lazy[maxx<<],val;
int n,q; void Pushup(int rt) {
sum[rt]=sum[rt<<]+sum[rt<<|];
} void build(int rt,int L,int R) {
lazy[rt]=;
if(L==R) {
scanf("%lld",&sum[rt]);
return;
}
int mid=(L+R)>>;
build(rt<<,L,mid);
build(rt<<|,mid+,R);
Pushup(rt);
} void Pushdown(int rt,int x) {
if(lazy[rt]) {
lazy[rt<<]+=lazy[rt];
lazy[rt<<|]+=lazy[rt];
sum[rt<<]+=(x-(x>>))*lazy[rt];//左子树加左边一半的值
sum[rt<<|]+=(x>>)*lazy[rt];//右子树同理
lazy[rt]=;//清空
}
} void Updata(int rt,int L,int R,int l,int r) {
if(L>=l&&R<=r) {
lazy[rt]+=val;//累加标记
sum[rt]+=(R-L+)*val;//更新值
return;
}
int mid=(L+R)>>;
Pushdown(rt,R-L+);//这里多了一个参数 L R区间的个数
if(l<=mid) Updata(rt<<,L,mid,l,r);
if(r>mid) Updata(rt<<|,mid+,R,l,r);
Pushup(rt);
} ll Query(int rt,int L,int R,int l,int r) {
if(L>=l&&R<=r)
return sum[rt];
ll ans=;
int mid=(L+R)>>;
Pushdown(rt,R-L+);
if(l<=mid) ans+=Query(rt<<,L,mid,l,r);
if(r>mid) ans+=Query(rt<<|,mid+,R,l,r);
Pushup(rt);
return ans;
} int main() {
while(~scanf("%d%d",&n,&q)) {
build(,,n);
char s[];
while(q--) {
scanf("%s",s);
int l,r;
if(s[]=='Q') {
scanf("%d%d",&l,&r);
printf("%lld\n",Query(,,n,l,r));
} else {
scanf("%d%d%lld",&l,&r,&val);
Updata(,,n,l,r);
}
}
}
}

借此机会学习了一波树状数组,有点难理解。

单点修改 区间查询  Updata(l,val)

区间修改 单点查询  引入差分数组 c[i]=d[i]-d[i-1]; Updata(l,val);  Updata(r+1,-val); ----明白树状数组就好理解了。把多加的减去

区间修改 区间查询  公式可以推到一下,sum[n]=n*(c[1]+c[2]+...c[n])-(0*c[1]+1*c[2]+2*c[3]+...+(n-1)*c[n]);

所以再维护一个 (i-1)*(a[i]-a[i-1]) , a为原数组。

Updata(l,(l-1)*val); Updata(r+1,-r*val);   原理同上。多加的减去。

(纯属个人理解。关键还是公式的推导,和树状数组的理解)

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
#define lowbit(x) (x&-x) int n,q;
const int maxn=;
ll a[maxn],val,c1[maxn],c2[maxn];//维护两个树状数组 void Updata(ll c[],int pos,ll val) {
while(pos<=n) {
c[pos]+=val;
pos+=lowbit(pos);
}
} ll getsum(ll c[],int pos) {
ll ans=;
while(pos>) {
ans+=c[pos];
pos-=lowbit(pos);
}
return ans;
} ll sigma(int r) {//公式推导
ll sum1=r*getsum(c1,r);
ll sum2=getsum(c2,r);
return sum1-sum2;
} ll Query(int l,int r) {//区间求和
return sigma(r)-sigma(l-);
} int main() {
while(~scanf("%d%d",&n,&q)) {
memset(c1,,sizeof(c1));memset(c2,,sizeof(c2));
for(int i=;i<=n;i++) {
scanf("%lld",&a[i]);
Updata(c1,i,a[i]-a[i-]);//维护a[i]-a[i-1]
Updata(c2,i,(i-)*(a[i]-a[i-]));//维护(i-1)*(a[i]-a[i-1])
}
char s[];
while(q--) {
int l,r;
scanf("%s",s);
if(s[]=='Q') {
scanf("%d%d",&l,&r);
printf("%lld\n",Query(l,r));
} else {
scanf("%d%d%lld",&l,&r,&val);
//更新操作有点难理解
Updata(c1,l,val);Updata(c1,r+,-val);
Updata(c2,l,(l-)*val);Updata(c2,r+,-r*val);
}
}
}
}

kuangbin专题七 POJ3468 A Simple Problem with Integers (线段树或树状数组)的更多相关文章

  1. poj3468 A Simple Problem with Integers (线段树区间最大值)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 92127   ...

  2. POJ3468 A Simple Problem with Integers —— 线段树 区间修改

    题目链接:https://vjudge.net/problem/POJ-3468 You have N integers, A1, A2, ... , AN. You need to deal wit ...

  3. POJ3468 A Simple Problem with Integers(线段树延时标记)

    题目地址http://poj.org/problem?id=3468 题目大意很简单,有两个操作,一个 Q a, b 查询区间[a, b]的和 C a, b, c让区间[a, b] 的每一个数+c 第 ...

  4. poj3468 A Simple Problem with Integers(线段树模板 功能:区间增减,区间求和)

    转载请注明出处:http://blog.csdn.net/u012860063 Description You have N integers, A1, A2, ... , AN. You need ...

  5. 线段树---poj3468 A Simple Problem with Integers:成段增减:区间求和

    poj3468 A Simple Problem with Integers 题意:O(-1) 思路:O(-1) 线段树功能:update:成段增减 query:区间求和 Sample Input 1 ...

  6. 2018 ACMICPC上海大都会赛重现赛 H - A Simple Problem with Integers (线段树,循环节)

    2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 H - A Simple Problem with Integers (线段树,循环节) 链接:https://ac.nowcoder.co ...

  7. poj------(3468)A Simple Problem with Integers(区间更新)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 60745   ...

  8. POJ3468 A Simple Problem with Integers 【段树】+【成段更新】

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 57666   ...

  9. [poj3468]A Simple Problem with Integers_线段树

    A Simple Problem with Integers 题目大意:给出n个数,区间加.查询区间和. 注释:1<=n,q<=100,000.(q为操作次数). 想法:嗯...学了这么长 ...

随机推荐

  1. Python多进程-进程锁

    多进程虽然不允许多个进程同时修改同一份数据,但是多进程也有锁,为了在屏幕上打印的时候不出现两个进程同时执行的显示错误 # -*- coding:utf-8 -*- __author__ = " ...

  2. webapi中使用token验证(JWT验证)

    本文介绍如何在webapi中使用JWT验证 准备 安装JWT安装包 System.IdentityModel.Tokens.Jwt 你的前端api登录请求的方法,参考 axios.get(" ...

  3. 记工作的变化--入住DB

    2013年11月1日----一个值得纪念的日子! 今天才是我作为一个劳动者,步入社会的真正开始. 以前一直觉得做技术的技术做好就行了不用在意其余的细节.现实是做人(沟通)比做技术更重要! 以前一直觉得 ...

  4. 10-12C#基础--运算符

    10-12C#基础--运算符 课前作业:班级内人数的姓名和年龄,分别写出之后并汇总. 一.运算符的分类 1.数学运算符(7个) 1)+(加号) 例: 2)-(减号) 例: 3)*(乘号) 例: 4)/ ...

  5. 来自T00ls的帖子-XSS的奇技淫巧

    T00LS在前段时间开启了markdown支持,这个漏洞也正是markdown的问题导致. Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定 ...

  6. java如何从cmd运行并使用text文件作为输入源的总结

    大家好,好几天没写东西了,又和大家见面了 首先,编译我们的.java文件,生成.class文件 使用命令 javac yourname.java 编译 然后使用java youname < yo ...

  7. 窗体控件JFrame的使用

    ---------------siwuxie095 工程名:TestUI 包名:com.siwuxie095.ui 类名:MyFrame.java 工程结构目录如下: 在 Source 界面和 Des ...

  8. win10获取超级管理员权限脚本实现

    建立一个TXT文件,把下面的脚本贴到里面,然后把后缀改成reg格式,双击添加到注册表就可以了, win10_1703版本亲测可用.... Windows Registry Editor Version ...

  9. JAVA语法规则总结

    单继承多实现 抽象类  抽象方法 使用关键字:abstract修饰的方法就是抽象方法; 抽象方法的形式:只有方法的声明,没有方法体; 抽象方法一般存在于父类中,相当于强制要求子类必须重写该方法,相当于 ...

  10. QGraphicsScene绘制网格背景

    博客转载自:https://blog.csdn.net/u010177010/article/details/51496038 //两条轴线QPolygonF myPolygon1; myPolygo ...