树状数组变形:带区间修改的树状数组

原理很简单,利用差分知识做的,只能单点查询,在性能上优于线段树,但没有区间查询功能。

 1 #include<bits/stdc++.h>
 2 #define f(i,a,b) for(int i=a;i<=b;i++)
 3 using namespace std;
 4
 5 const int N=5e5+5;
 6 int n,q,opt,le,ri,pos,val;
 7 int a[N];
 8 int tree[N];
 9 #define lowbit(x) (x&(-x))
10 void update(int pos,int val){
11     if(pos<=0) return;
12     while(pos<=n){
13         tree[pos]+=val;
14         pos+=lowbit(pos);
15     }
16 }
17 int sum_1_to_pos(int pos){
18     int ans=0;
19     while(pos>0){
20         ans+=tree[pos];
21         pos-=lowbit(pos);
22     }
23     return ans;
24 }
25 #define query(x,y) (sum_1_to_pos(y)-sum_1_to_pos(x-1))
26
27 int main(){
28     scanf("%d%d",&n,&q);
29     scanf("%d",&a[1]);
30     f(i,2,n) scanf("%d",&a[i]),update(i-1,a[i]-a[i-1]);
31     f(i,1,q){
32         scanf("%d",&opt);
33         if(opt==1){
34             scanf("%d%d%d",&le,&ri,&val);
35             update(le-1,val);
36             update(ri,-val);
37             if(le==1) a[1]+=val;
38             //cout<<"array is:\n";
39             //f(i,1,n) cout<<i<<" : "<<a[1]+query(1,i-1)<<endl;
40         }
41         else{
42             scanf("%d",&pos);
43             printf("%d\n",a[1]+query(1,pos-1));
44         }
45     }
46 } 

原文地址:https://www.cnblogs.com/St-Lovaer/p/12263997.html

时间: 2024-11-07 08:03:09

树状数组变形:带区间修改的树状数组的相关文章

支持区间修改的树状数组

支持区间修改的树状数组 原理 对于一个数组\(a\),以及\(a\)的差分\(c\),显然有\(c[i]=a[i]-a[i-1]\) 那么对于数组a的前缀和有 \(\sum_{i=1}^n{a_i}=c[1]+(c[1]+c[2])+...(c[1]+c[2]+...+c[n])\) 进一步的: \(\sum_{i=1}^n{a_i}=c[1]*n+c[2]*(n-1)+...+c[n]*(n-n+1)\) 展开括号内 \(\sum_{i=1}^n{a_i}=c[1]*n+c[2]*n+...+

[BZOJ 4826]影魔 区间修改主席树 标记永久化

为了这道题还特地去学了标记永久化,可能对于区间修改主席树或者树套树比较有用吧OvO 我们可以把答案分为两部分:p1造成的和p2造成的 我们枚举序列,用单调栈求出序列每一个位置i,左右边第一个比它大的L,R 开三棵主席树tree1 tree2 tree3 把L扔进tree1的R位置(单点+1),L+1~i-1扔进tree2的R位置,i+1~R-1扔进tree3的L位置(区间+1) 然后询问[l,r]的时候,求出三棵区间主席树 p1造成的贡献为区间tree1内大于等于L的个数 p2造成的贡献为区间t

【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询

Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Output 输出每个询问的结果 Sample Input 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 Sample Output 1 2 1 HINT

树状数组模板(区间修改+单点查询)

很巧妙的用了差分建树,解决区间修改的问题 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=5e5+5; 5 6 int n,m; 7 int a[maxn]; 8 ll tree[maxn]; 9 10 int lowbit(int x){ 11 return x&(-x); 12 } 13 14 void add(int idx,int v){ 15

线段树(二):区间修改

上一节介绍了点修改与区间查询的线段树,事实上,线段树还可以做得更多.本节讨论区间修改问题. 给出一个$n$个元素的数组$A_1,A_2,...,A_n$,你的任务是设计一个数据结构,支持以下两种操作: $Add(L,R,v)$:把$A_L,A_{L+1}, ..., A_R$的值全部增加$v$ $Query(L, R)$:计算子序列$A_L,A_{L+1},...,A_R$的元素和.最大值和最小值 点修改只会影响到$logn$个结点,但区间修改在最坏情况下会影响到树中的所有结点,比如,如果对整个

hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

Bzoj 3050: [Usaco2013 Jan]Seating(线段树裸题,然而区间修改标记下放和讨论Push_up很揪心)

题目链接 题意:开始有一个空白的区间,每次可能进行两个操作:A 将一个长度为p的区间加入一段连续空白的位置 L:一个区间恢复空白:要求出A不能进行的次数. 非常裸的线段树题目,用线段树统计最大的空白区间,每个节点需要记录当前区间的最长空白区间,从左端开始的最长空白区间,从右端开始的最长空白区间.Push_up的时候要讨论下,可以分别取[l,mid]和[mid+1,r]的最大空白区间,也可以用[l,mid]的从右端开始的最长空白区间+[mid+1,r]从左端开始的最大空白区间. 每次A的时候,就查

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

A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4032    Accepted Submission(s): 1255 Problem Description Let A1, A2, ... , AN be N elements. You need to deal with

poj 3067 poj 2481 树状数组变形+对区间排序

这种问题先对区间和线段进行排序,排序方法见代码cmp 然后分析其中一个点,用sum求值 poj 3067 Description Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coast and M cities on the West coast (M <