初始給出n個數,a[1]~a[n]
有m個操作
1,把a[l]~a[r]加上x
2,把a[l]~a[r]減去x後和0取max
3,把a[l]~a[r]和x取max
4,輸出a[x]
5,輸出a[x]的歷史最大值(即出現過的值的最大值)
令標記(a,b)表示對於x進行max(x+a,b)那麼
操作1相當於(x,-inf)
2相當於(-x,0)
3相當於(0,x)
如果乙個數x先經過(a,b),再經過(c,d),會怎樣呢?
x=max(max((a+x),b)+c,d)=max(a+c+x,max(b+c,d))
所以可以把標記合併為(a+c,max(b+c,d))
相當於記錄乙個歷史最大值標記,無論x的值為何,經過這個標記一定是歷史最大值。
其實可以把乙個標記看做乙個一次函式和乙個與x軸平行的函式取max,每次操作i記做標記fi,設fi=f0~i合併後的標記
那歷史最大值標記肯定是(max(fi_a),max(fi_b))
用線段樹來維護這些標記,對於線段樹上的乙個節點,假如當前它存在有標記,他的兒子的標記的時間顯然是比它要先的,否則它的標記肯定已經下傳了,
它的兒子的歷史最大值標記應該由它的歷史最大標記和它的兒子的當前標記合併後再拿去更新(因為它的fi=fj+1~i(j
,而它的兒子的fj=fj』+1~j(j
′,所以它歷史最大值標記和它的兒子相比,缺少fj』+1~j,所以和fj合併即可)
,當前標記應該要和它的當前標記合併.
#include
#include
#include
#define ll long long
#define inf 1e17
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b)for(i=a;i>=b;i--)
#define min(a,b) (a#define max(a,b) (a>b?a:b)
using namespace std;
const int maxn=5e5+5;
int ww;char ch;
inline int
read()
int i,j,n,m,x;ll a[maxn];
struct artree[maxn*4],p,ze=(ar);
ar operator +=(ar &a,ar p)
void down(int k)
void change(int k,int l,int r,int a,int b)
intm=(l+r)>>1,lk=k<<1,rk=lk+1;
if (b<=m) change(lk,l,m,a,b);else
if (a>m) change(rk,m+1,r,a,b);else
change(lk,l,m,a,m),change(rk,m+1,r,m+1,b);
}void find(int k,int l,int r)
down(k);
intm=(l+r)>>1,lk=k<<1,rk=lk+1;
if (x
<=m) find(lk,l,m);else find(rk,m+1,r);
}int main();else
if (o==2) p=(ar);else
p=(ar);
change(1,1,n,l,r);
}else
}}
uoj164 清華集訓2015 V
題目鏈結 164.清華集訓2015 v 大佬的部落格 jefflyy 這個東西,詭異的標記下傳。一共有五種操作,區間加法,區間減法 減到0就不減了 區間覆蓋,單點詢問,單點歷史最大值。非常巧妙的使用了乙個pair來進行標記。y max x a,b 就是可以看做建立乙個直角座標系,其中x軸表示原數字,...
UOJ 164 清華集訓2015V
qwqzcysky真是菜死了,這是我剛上高一的時候坤爺在夏令營講的,可是今天才切掉 想想也神奇,乙個2016.11才學會線段樹的菜雞,夏令營的時候居然聽過segment tree beats?所以我們來看下這個神奇的segment tree beats.我們維護乙個神奇的標記二元組 x,y 在樹點上...
UOJ 164 清華集訓2015 V
這道題由於是單點詢問,所以異常好寫。注意到每種修改操作都可以用乙個標記 a,b 表示。標記 a,b 的意義就是 x max 同時這種標記也是支援合併的。有 a,b c,d a c,max 用上這種標記的話,1 操作就是 x,0 2 操作就是 x,0 3 操作就是 inf,x 要查詢單點值的話只要把所...