一段序列,支援五個操作。
1、區間加
2、區間減,然後對0取max
3、區間賦值
4、單點查詢
5、單點查詢歷史最大值
前三個操作可以看成一種:給原數加a,再和b取max。即
1、x=max(x+a,0)
2、x=max(x-a,0)
3、x=max(x-inf,b)
發現標記max(x+a1,b1)和max(x+a2,b2)可以合併為max(x+a1+a2,max(b1+a2,b2))
然後只剩下第5種操作。
再給每個點維護乙個歷史最大值標記。合併後標記=max(x+max(a1,a2),max(b1,b2))。
注意標記必須打、pushdown的順序必須按**裡那樣來。不然會是錯的。
可以通過這樣一組小資料感性理解一下。
4 41 2 3 4
1 1 2 5
2 1 2 1
1 1 4 2
5 2注意這個**不加inline會t,加了inline跑得比o2還筷。
#include#include#include#includeusing namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define sqr(x) ((x)*(x))
#define g getchar()
#define ll long long
#define pll pair#define mkp make_pair
#define x first
#define y second
#define n 500005
#define nn 2000005
#define inf 1000000000000000ll
int n;ll a[n],la1[nn],lb1[nn],la2[nn],lb2[nn],a1[nn],b1[nn],a2[nn],b2[nn];
inline int read()
inline void add(ll a,ll b,int num)
inline void add2(ll a,ll b,int num)
inline void pd(int num)
void ins(int l,int r,ll a,ll b,int l,int r,int num)
int mid=l+r>>1;pd(num);
if(l<=mid)ins(l,r,a,b,l,mid,num<<1);
if(r>mid)ins(l,r,a,b,mid+1,r,num<<1|1);
}ll query1(int x,int l,int r,int num)
ll query2(int x,int l,int r,int num)
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
這道題由於是單點詢問,所以異常好寫。注意到每種修改操作都可以用乙個標記 a,b 表示。標記 a,b 的意義就是 x max 同時這種標記也是支援合併的。有 a,b c,d a c,max 用上這種標記的話,1 操作就是 x,0 2 操作就是 x,0 3 操作就是 inf,x 要查詢單點值的話只要把所...