這道題由於是單點詢問,所以異常好寫。
注意到每種修改操作都可以用乙個標記\((a,b)\)表示。標記\((a,b)\)的意義就是\(x= \max\\)
同時這種標記也是支援合併的。有\((a,b)+(c,d)=(a+c,\max\)\)
用上這種標記的話,\(1\)操作就是\((x,0)\),\(2\)操作就是\((-x,0)\),\(3\)操作就是\((-inf,x)\)。
要查詢單點值的話只要把所有標記都下放了就好了。
這種標記也支援取\(\max\)。即,\(\max\=(\max\,\max\)\)。本質上就是乙個分段函式取\(\max\)的過程。
所以最後一問再維護乙個歷史最大值這道題就做完了。注意下傳標記時先傳歷史標記。
還有乙個要注意的地方:標記\((a,b)\)裡的\(a\)實際上是\(\max\\)。注意修改的時候和\(-inf\)取個\(max\),不然很容易就爆掉了。
下面貼**:
#include#include#include#include#include#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)#define max(a,b) (a>b?a:b)
#define maxn 500010
#define inf (1ll<<60)
using namespace std;
typedef long long llg;
int n,m,l,r;
llg na[maxn<<2],nb[maxn<<2];
llg pa[maxn<<2],pb[maxn<<2],za,zb;
int getint()
void pushdown(int u)
na[u]=nb[u]=pa[u]=pb[u]=0;
}void build(int u,int l,int r)
void add(int u,int l,int r)
pushdown(u);
if(l<=mid) add(lc,l,mid);
if(r>mid) add(lv,mid+1,r);
}void query(bool w)
za=w?na[u]:pa[u];
zb=w?nb[u]:pb[u];
}int main()
else
} return 0;
}
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
164.清華集訓2015 v 貌似是乙個 題,是jls線段樹的題目。首先我們定義一種標記 a,b 表示給這個區間先加上 a 再跟 b 取 max 不難發現題目裡提到的三種操作分別都可以用這樣的標記來代替 1 區間加 v v,inf 2 區間減 v v,0 3 區間覆蓋 inf,v 考慮合併兩個標記 ...