樹狀陣列(區間更新)差分思想
已知一個數列,你需要進行下面兩種操作:
1.將某區間每一個數數加上x
2.求出某一個數的和
題:
第一行包含兩個整數N、M,分別表示該數列數字的個數和操作的總個數。
第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。
接下來M行每行包含2或4個整數,表示一個操作,具體如下:
操作1: 格式:1 x y k 含義:將區間[x,y]內每個數加上k
操作2: 格式:2 x 含義:輸出第x個數的值
輸出格式:
輸出包含若干行整數,即為所有操作2的結果。
輸入輸出樣例
輸入樣例#1: 複製
5 5 1 5 4 2 3 1 2 4 2 2 3 1 1 5 -1 1 3 5 7 2 4
輸出樣例#1: 複製
6
10
說明
時空限制:1000ms,128M
資料規模:
對於30%的資料:N<=8,M<=10
對於70%的資料:N<=10000,M<=10000
對於100%的資料:N<=500000,M<=500000
樣例說明:
故輸出結果為6、10
關於差分:
設陣列a[]={1,6,8,5,10},那麼差分陣列b[]={1,5,2,-3,5}
也就是說b[i]=a[i]-a[i-1];(a[0]=0;),那麼a[i]=b[1]+....+b[i];(這個很好證的)。//理解這裡很重要
假如區間[2,4]都加上2的話
a陣列變為a[]={1,8,10,7,10},b陣列變為b={1,7,2,-3,3};
發現了沒有,b陣列只有b[2]和b[5]變了,因為區間[2,4]是同時加上2的,所以在區間內b[i]-b[i-1]是不變的.
所以對區間[x,y]進行修改,只用修改b[x]與b[y+1]:
b[x]=b[x]+k;b[y+1]=b[y+1]-k;
這個題目是樹狀陣列的一個拓展,在樹狀陣列中可以用前 i 項的和來表示第 i 個數.
那麼當對 x ~ y 的區間進行修改的時候需要在樹狀陣列中的第 x 個位置 + k, 第 y + 1 個位置 -k
這樣便維護了這個樹狀陣列
輸出時候直接輸出查詢即可
#include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> #include <iostream> #include <queue> #include <list> #include <deque> #include <vector> #include <map> #define LL long long int lowbit(int x) { return x&(-x); } const int MAXN =1e6+7; const long long MAX=0x7f7f7f3f; using namespace std; void read(int &x){ char ch = getchar();x = 0; for (; ch < '0' || ch > '9'; ch = getchar()); for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; } long long arr[MAXN]={0},c[MAXN]={0}; long long n,m,k; long long sum(long long x,long long c[]) { long long ret=0; for(int i=x;i>0;i-=lowbit(i)) { ret+=arr[i]; //ret+=c[i]; } return ret; }/* void updata(int x,int val,int n) { for(int i=x;i<=n;i+=lowbit(i)) { c[i]+=val; // x+=lowbit((x)); } }*/ void updata(long long x,long long val) { // int i=l; for(int i=x;i<=n;i+=lowbit(i)) { // c[i]+=val; arr[i]+=val; } } int main() { ios::sync_with_stdio(false); // int n,m,k; cin>>n>>m; long long num; long long last=0,now; for(int i=1;i<=n;i++) { // cin>>arr[i]; //updata(i,arr[i]); cin>>now; updata(i,now-last); last=now; } while(m--) { int l,r,val; int x; cin>>k; if(k==1) { cin>>l>>r>>val; updata(l,val); updata(r+1,-val); } else { cin>>x; //int ans=sum(r,c,n)-sum(l-1,c,n); // cout<<sum(r,c,n)<<" "<<sum(l,c,n)<<endl; cout<<sum(x,c)<<endl; } } return 0; }
相關推薦
樹狀陣列(區間更新)差分思想
已知一個數列,你需要進行下面兩種操作: 1.將某區間每一個數數加上x 2.求出某一個數的和 題: 第一行包含兩個整數N、M,分別表示該數列數字的個數和操作的總個數。 第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。 接下來M行每行包含2或
Color the ball (樹狀陣列,區間更新,單點查詢)
N個氣球排成一排,從左到右依次編號為1,2,3....N.每次給定2個整數a b(a <= b),lele便為騎上他的“小飛鴿"牌電動車從氣球a開始到氣球b依次給每個氣球塗一次顏色。但是N次以後lele已經忘記了第I個氣球已經塗過幾次顏色了,你能幫他算出每個氣球被塗過幾次顏色嗎? Inpu
樹狀陣列(區間修改單點查詢)洛谷:樹狀陣列2
模版和單點修改區間查詢差不多 樹狀陣列(單點修改區間查詢) https://blog.csdn.net/johnwayne0317/article/details/84927585 然後用到了差分陣列 https://blog.csdn.net/johnwayne0317/a
樹狀陣列(區間修改,單點查詢)
這裡介紹樹狀陣列+差分思想,算是對下面大神的補充吧。 何為差分現在我們有一個從小到大的數列a[] a{1,3,6,8,9}; 然後還有一個差分陣列b[] b{1,2,3,2,1} 相信某些小夥伴已經看
二維樹狀陣列(區間修改,單點查詢)
好像不管是幾維都和一維原理差不多,多了一個維度也就多了一層迴圈而已(QAQ) #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath&g
淺談樹狀陣列(解析+模板)
也不知道是什麼時候開始,對於曾經學過的演算法都不太用了 遇到區間修改,區間最值就知道用線段樹,什麼樹狀陣列啊,st表啊都忘得差不多了 最近幾次模考被卡翻了,於是又想起這些老朋友 來填個坑 首先我們要明確一點,樹狀陣列只能維護求和,不能維護區間最值 樹狀陣列利用了分治的思想,層數為
樹狀陣列(未完成)
(建議邊對著圖邊看解釋) 背景:若線上地修改數列裡某個數的值,其維護【字首和】的複雜度太高 樹狀陣列c性質: 1、c[i]的管轄區間以a[i]結尾,從某種意義來說,c[i]與a[i]一一對應 2、c[i]的管轄區間長2^k,k
樹狀陣列的區間更新和區間查詢
對於區間修改、區間查詢這樣的簡單問題,打一大堆線段樹確實是不划算,所以學習下區間查詢+區間修改的樹狀陣列 設原陣列是a[n],差分陣列c[n],c[i]=a[i]-a[i-1], 那麼明顯地a[i]=sigma (c[i]),如果想要修改a[i]到a[j](比如+v),只需
樹狀陣列之區間更新與查詢
具體思路:由於樹狀陣列裸的模板只能通過陣列求區間和,而對於區間的更新的查詢無法實現,所以通過多個數組進行輔助。 具體公式,通過三個陣列實現。第一個陣列記錄第一組的字首和。然後如果是更新的話,舉個例子,一共有10個數,1~n.在5 8 之間每一個數加3,也就是總的和在原來的基礎上上加
【專題】樹狀陣列(完整版)
傳統陣列(共n個元素)的元素修改和連續元素求和的複雜度分別為O(1)和O(n)。樹狀陣列通過將線性結構轉換成偽樹狀結構(線性結構只能逐個掃描元素,而樹狀結構可以實現跳躍式掃描),使得修改和求和複雜度均為O(lgn),大大提高了整體效率。 給定序列(數列)A,我們設一個數組C滿足 C[i] = A[i–
樹狀陣列模板區間更新 區間詢問
14、樹狀陣列 (1)、單點增減+區間求和 思路:C[x]表示該點的元素:sum(x)=C[1]+C[2]+……C[x]int arr[MAXN]; inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(
樹狀陣列的區間加法(差分)
應用差分原理,實現樹狀陣列區間加法 差分:a區間[1, 2, 3, 4, 5],則差分割槽間為[1, 1, 1, 1, 1]即bn = an - an-1,an = b1 +…+ bn 如果對區間[2, 4]都加上2,則a[1, 5, 6, 7, 5], 差分割槽間[1, 4, 1,
樹狀陣列單點更新和區間更新,二維陣列poj2155(區間更新,單點查詢)(已加入區間修改區間查詢)
普通的樹狀陣列C[i]=a[i]+a[i-1]+...a[i-2^k+1]+...+a[1]; 但是所有樹狀陣列都是向上更新,向下求和。 1)、單點增減+區間求和 思路:C[x]表示該點的元素:sum(x)=C[1]+C[2]+……C[x] [cpp] view p
hdu1556 Color the ball (樹狀陣列應用型別二) 【區間更新 單點求值】
題目連線:http://acm.hdu.edu.cn/showproblem.php?pid=1556 Problem Description N個氣球排成一排,從左到右依次編號為1,2,3....N.每次給定2個整數a b(a <= b),lele便為騎上他
敵兵佈陣 (樹狀陣列應用型別一)【單點更新與區間求和】
題目連線:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Problem Description C國的死對頭A國這段時間正在進行軍事演習,所以C國間諜頭子Derek和他手下Tidy又開始忙乎了。A國在海岸線沿直線佈置了N個
【模板】樹狀陣列(差分)
題目描述 如題,已知一個數列,你需要進行下面兩種操作: 1.將某區間每一個數數加上x 2.求出某一個數的和 輸入輸出格式 輸入格式: 第一行包含兩個整數N、M,分別表示該數列數字的個數和操作的總個數。 第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值
神奇的差分法(內附樹狀陣列的一點擴充套件)
差分法是我們所用的一個強力的武器! 有這把武器你就可以統治世界。。。 一個大佬曾經講過,一但碰到區間修改的題,就要優先考慮差分。 目錄 普通差分法 差分套差分(二階差分) 高階差分 樹上差分(點的意義與邊的意義) 例題 普通差分法
樹狀陣列(單點修改區間查詢)
lowbit(重要!) lowbit是用來取出二進位制中最低位數的1所代表的二進位制的值。 只需要記下程式碼就行了 int lowbit(int x){ return x&(-x); } add單點修改字首和 將一個樹的最子節點修改,則其父節點也需要更改,父
Non Super Boring Substring —— 馬拉車+樹狀陣列(求不包含迴文串區間的個數)
You’ll be given a string S and an integer K. You have to find the number of non super-boring substring inside S. A substring is
POJ 2481 Cows 樹狀陣列 單點更新 (每個集合是幾個集合的真子集)
Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensi