這道題題目簡潔新穎,吸引讀者閱讀興趣...
目錄正解
注:更完整的版本在這裡。點這裡
需要你維護長度為n的序列並支援下列操作:
區間加法;
區間賦值;
區間每個 \(a_i\) 變成 \(\max(a_i-t,0)\);
單點詢問值
單點詢問歷史最大值
\(n,m≤500000\),其中 \(m\) 為運算元。
首先考慮,如果這道題沒有歷史版本我們該怎麼做?
其實很簡單,這裡我就不贅述了 其實是我懶得說 。
那麼我們考慮,對於這個 \(5\) 操作,我們應該怎麼做?
首先,分析 \(3\) 操作,這是乙個很特殊的操作。
對於每個 \(a_i\) ,將 \(a_i\) 修改為 \(\max(a_i-t,0)\),我們把它寫成函式,即
\[f(x)=\max(x-t,0)
\]寫成一般形式,即
\[f(x)=\max(x+a,b)
\]那麼,我們可以輕鬆地畫出這個函式的影象:
考慮能否將兩個函式 \(f_1(x),f_2(x)\) 的最大值全部合併,成為 \(g(x)\),即如下圖
顯然是可行的,具體如何實現請自行思考,如果實在不行,看看**也好啊。
現在,我們來看這樣的函式能不能疊加,即對於 \(f(x)=\max(x+a,b)\),能不能給 \(a+\delta\) 或者 \(b+\delta\)。
顯然這也是可行的,即新的 \(f'(x)=\max(x+a+\delta,b)\) 或者是 \(f'(x)=\max(x+a,b+\delta)\)。
發現這個函式有疊加性以及能夠維護函式最大,發現似乎可以用這樣的函式來做這道題,但是,需要對我們的操作進行一些變換:
設標記 \((a,b)\) 表示將 \(x\) 變成 \(\max(a+x,b)\) 。假設對乙個位置作用的標記對應函式依次為 \(f_1 (x),f_2 (x)\ldots,f_k (x)\)
歷史最大值對應函式為 \(\max\(……f_1(x)))\}\)
如若能維護出該函式,歷史最大值即可維護出。
可以發現將兩個這樣函式取 \(\max\) 後仍然是乙個形式一樣的函式(見上面的圖)。於是歷史最大值的函式即可維護。用線段樹在每個區間維護當前標記的函式和歷史最大值的函式即可,這兩個都支援 \(\mathcal o(1)\) 合併。於是複雜度為 \(\mathcal o(n\logn)\)。
#include #include #include #include #include using namespace std;
// #define ndebug
#include namespace elaina
templateinline void getmin(t& x, const t rhs)
templateinline void getmax(t& x, const t rhs)
templateinline t readin(t x)
}using namespace elaina;
const int maxn=5e5;
const ll inf=1ll<<50;
ll x[maxn+5];
int n, m;
namespace saya;
}inline func operator ^(const func& rhs) const;
}inline ll operator ()(const ll& x) const
};func tag[maxn<<2|2], histag[maxn<<2|2];
#define ls (i<<1)
#define rs (i<<1|1)
#define mid ((l+r)>>1)
#define fa (i>>1)
#define _lhs ls, l, mid
#define _rhs rs, mid+1, r
#define _this i, l, r
inline void update(int i)
inline void pushdown(int i);
}void build(int i, int l, int r);
if(l==r) return;
build(_lhs), build(_rhs);
}void modify(int l, int r, func f, int i, int l, int r)
pushdown(i);
if(l<=mid) modify(l, r, f, _lhs);
if(mid
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 要查詢單點值的話只要把所...