1. 程式人生 > >zkw線段樹,區間修改,最值查詢(差分)

zkw線段樹,區間修改,最值查詢(差分)

#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<cstring>
using namespace std;
const int N=50010;
int T,M,n,s,t,num,Max[N<<3],Min[N<<3];
char op[3];
void build(){
	for(int i=M+1;i<=M+n;i++)
		scanf("%d",&Max[i]),Min[i]=Max[i];
	for(int i=M;i>0;i--){
		Max[i]=max(Max[i<<1],Max[i<<1|1]);
		Max[i<<1]-=Max[i],Max[i<<1|1]-=Max[i];
		Min[i]=min(Min[i<<1],Min[i<<1|1]);
		Min[i<<1]-=Min[i],Min[i<<1|1]-=Min[i];
	}
}
void update(int pos,int val){
    int a;
    Max[pos+M]+=val,Min[pos+M]+=val;
    for(pos=pos+M;pos;pos>>=1){
        a=max(Max[pos<<1],Max[pos<<1|1]);
        Max[pos<<1]-=a,Max[pos<<1|1]-=a,Max[pos]+=a;
		
        a=min(Min[pos<<1],Min[pos<<1|1]);
        Min[pos<<1]-=a,Min[pos<<1|1]-=a,Min[pos]+=a;
    }
}
void update(int s,int t,int val){
	int a;
	if(s==t){
		update(s,val);return ;
	}
	Max[s+M]+=val,Min[s+M]+=val;
	Max[t+M]+=val,Min[t+M]+=val;
	for(s=s+M,t=t+M;s^t^1;s>>=1,t>>=1){
		if(~s&1)	Max[s^1]+=val,Min[s^1]+=val;
		if(t&1)	Max[t^1]+=val,Min[t^1]+=val;
		
		a=max(Max[s<<1],Max[s<<1|1]);
		Max[s<<1]-=a,Max[s<<1|1]-=a,Max[s]+=a;
		a=min(Min[s<<1],Min[s<<1|1]);
		Min[s<<1]-=a,Min[s<<1|1]-=a,Min[s]+=a;
		
		a=max(Max[t<<1],Max[t<<1|1]);
		Max[t<<1]-=a,Max[t<<1|1]-=a,Max[t]+=a;
		a=min(Min[t<<1],Min[t<<1|1]);
		Min[t<<1]-=a,Min[t<<1|1]-=a,Min[t]+=a;
	}
	a=max(Max[t<<1],Max[t<<1|1]);
	Max[t<<1]-=a,Max[t<<1|1]-=a,Max[t]+=a;
	a=min(Min[t<<1],Min[t<<1|1]);
	Min[t<<1]-=a,Min[t<<1|1]-=a,Min[t]+=a;
	while(s){
		a=max(Max[s<<1],Max[s<<1|1]);
		Max[s<<1]-=a,Max[s<<1|1]-=a,Max[s]+=a;
		a=min(Min[s<<1],Min[s<<1|1]);
		Min[s<<1]-=a,Min[s<<1|1]-=a,Min[s]+=a;
		s>>=1;
	}
}
int getmax(int s,int t){
	int L=0,R=0,res=0;
	if(s==t){
		while(s)	res+=Max[s],s>>=1;
		return res;
	}
	for(s=s+M,t=t+M;s^t^1;s>>=1,t>>=1){
		L+=Max[s],R+=Max[t];
		if(~s&1)	L=max(L,Max[s^1]);
		if(t&1)	R=max(R,Max[t^1]);
	}
	res=max(L+Max[s],R+Max[t]);
	while(s)	res+=Max[s>>=1];
	return res;
}
int getmin(int s,int t){
	int L=0,R=0,res=0;
	if(s==t){
		while(s)	res+=Max[s],s>>=1;
		return res;
	}
	for(s=s+M,t=t+M;s^t^1;s>>=1,t>>=1){
		L+=Min[s],R+=Min[t];
		if(~s&1)	L=min(L,Min[s^1]);
		if(t&1)	R=min(R,Min[t^1]);
	}
	res=min(L+Min[s],R+Min[t]);
	while(s)	res+=Min[s>>=1];
	return res;
}
int main(){
    scanf("%d %d",&n,&T);
	for(M=1;M<n;M<<=1);
	M--,build();
	while(T--){
		scanf("%s%d%d",op,&s,&t);
		if(op[0]=='Q')	printf("%d\n",getmax(s,t)-getmin(s,t));
		else scanf("%d",&num),update(s,t,num);
	}
}

相關推薦

zkw線段區間修改查詢

#include<algorithm> #include<cstdio> #include<iostream> #include<cstdlib> #include<ctime> #include<cmath

BZOJ1513:線段線段實現二維區間修改查詢

name names algo getch oid min 投影 協調 pan 我們經常提及的二維線段樹有兩種寫法,一種是四分樹,一種是樹套樹,寫成四分樹的都是神仙。 樹套樹寫法還是比較好理解的,不過要是讓自己硬套的話可能很不容易套出來的 這裏的二維線段樹,外層線段樹是對方

POJ 2019 Cornfields 二維線段的初始化與查詢

popu def comm init 都沒有 data- ont emp class 模板到不行。。連更新都沒有。。。存個模板。 理解留到小結的時候再寫。 #include <algorithm> #include <iostream>

線段維護區間(平方和立方和)修改區間(加乘)

題目地址 /* * @Author: hannibal * @Date: 2018-08-07 10:42:26 * @Last Modified by: hannibal * @Last Modified time: 2018-08-07 17:08:

線段模板:點修改區間修改

#include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #includ

HDU 4302(zkw線段-單點修改區間

Holedox Eating Problem Description Holedox在一條長度為L的線上. Holedox能在線上移動,線上會時不時的出現蛋糕(保證是整點)。Holedox會在想吃蛋糕時去最近的有蛋糕的點吃,如果左右的最近蛋糕與它的距離相等,它會按上一

HDU - 1166 敵兵布陣 (線段+單點修改區間查詢

如果 scan mes style 直線 print clas 電話 魷魚 C國的死對頭A國這段時間正在進行軍事演習,所以C國間諜頭子Derek和他手下Tidy又開始忙乎了。A國在海岸線沿直線布置了N個工兵營地,Derek和Tidy的任務就是要監視這些工兵營地的活動情況。由

zkw線段解決區間rmq

zkw線段樹具體內容請百度統計的力量(這是他講的時候所用的ppt的名字) 今天我們就來完整的寫一個zkw線段樹。 正如他在ppt裡講的 *差分是化絕對為相對的重要手段 *標記永久化後就是值,只不過這種值是相對的 *計算答案時可以利用從節點到根部的資訊 在zkw樹中,每個節

動態開點永久標記線段區間修改查詢

#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #define

hdu 5381 The sum of gcd線段等差數列區間修改+單點查詢

題意: 給出一個數組a,叫你每次詢問如下等式的值。 f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj) 解析: 思考了很久終於理解了學長的思路 給你一個序列,這個序列的子序列gcd的個數不會超過logN個(N為

【AC軍團週報第四周第一篇】線段從入門到入土【4】未完成

本文章連載AC軍團週報 -> 線段樹 : 從入門到入土【4】 前言 從前有一位遠古神犇,他彙集各大資料結構之精華,經過艱苦卓絕的研究,終於煉製成了一種新的,更簡潔的,更快的線段樹——zkw線段樹 (大霧) 四、zkw線段樹基礎 我們已經學過了線段樹的基礎了,相信大家已經熟練掌握線段樹大概的樣

狀陣列的區間加法

應用差分原理,實現樹狀陣列區間加法 差分: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,

區間查詢RMQ

ST演算法 預處理第i位起連續2^k個數的最大值,快速查詢。 說明:定義陣列dp[i][j]表示 從第i位起連續2^j個數 的最大值。 (區間內有2^j個數) 例子: 2 5 9 6 3 1

【模板】狀陣列

題目描述 如題,已知一個數列,你需要進行下面兩種操作: 1.將某區間每一個數數加上x 2.求出某一個數的和 輸入輸出格式 輸入格式: 第一行包含兩個整數N、M,分別表示該數列數字的個數和操作的總個數。 第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值

ccf歷年第四題java解答之-201412-4-優灌溉100

使用kruskal求解,耗時943ms,得分100 徘徊在超時的邊緣,同樣的程式碼,有時候提交是100分,有時候是超時90分,還有時候是超時80分== import java.util.ArrayList; import java.util.Collections; import jav

2018.09.26【TJOI2017】【BZOJ4888】【洛谷P3760】異或和狀陣列

洛谷傳送門 解析: 額,TJOITJOITJOI連續兩年考了位運算。。。 我還能說什麼。。。 PS:zxyoiPS:zxyoiPS:zxyoi不是天津oieroieroier。 思路: 一般位運算都

7-26 大公約數和小公倍數 15

本題要求兩個給定正整數的最大公約數和最小公倍數。 輸入格式: 輸入在一行中給出兩個正整數M和N(≤1000)。 輸出格式: 在一行中順序輸出M和N的最大公約數和最小公倍數,兩數字間以1空格分隔。 輸入樣例: 511 292 輸出樣例: 73 2044 鳴謝

7-6 大公約數和小公倍數15

7-6 最大公約數和最小公倍數(15 分) 本題要求兩個給定正整數的最大公約數和最小公倍數。 輸入格式: 輸入在一行中給出兩個正整數M和N(≤1000)。 輸出格式: 在一行中順序輸出M和

ccf 201412-4 優灌溉 100

問題描述   雷雷承包了很多片麥田,為了灌溉這些麥田,雷雷在第一個麥田挖了一口很深的水井,所有的麥田都從這口井來引水灌溉。   為了灌溉,雷雷需要建立一些水渠,以連線水井和麥田,雷雷也可以利用部分麥田作為“中轉站”,利用水渠連線不同的麥田,這樣只要一片麥田

CCF201609-1 大波動100

問題描述  小明正在利用股票的波動程度來研究股票。小明拿到了一隻股票每天收盤時的價格,他想知道,這隻股票連續幾天的最大波動值是多少,即在這幾天中某天收盤價格與前一天收盤價格之差的絕對值最大是多少。輸入格式  輸入的第一行包含了一個整數n,表示小明拿到的收盤價格的連續天數。  第二行包含n個正整數,依次表示每天