首先沒有限制的話排個序就完事了。
如果有限制的話,顯然我們需要幹的事情就是做出修正。
按照權值從小到大排序。
考慮什麼情況下非法,權值小的依賴權值大的。
這個時候的修正非常明顯,把這個區間拎出來,無依賴的公升序,然後有依賴的降序排在後面。
這樣的區間可以通過一次差分字首和找出來。
容易注意到有的時候我們把若干個區間合併可以得到更優的答案。
簡單討論可以發現,如果不是全部合併,必然是字首合併一段,中間全部不合併,字尾合併一段,找到這個合併的位置即可。
注意權值從大到小是等價的,我們還要把權值乘上-1再做一遍。
**:
#include
#define ll long long
#define re register
#define cs const
namespace io
template
<
typename t>t get_integer()
inline
intgi()
inline ll gl()
char obuf[
30000007],
*oh=obuf,ch[23]
;template
<
typename t>
void
print
(t a,
char c)
struct obuf_flusher
}flusher;
}using
namespace io;
using std::cerr;
using std::cout;
using pli=std::pairint>
;#define fi first
#define se second
cs int n=
1e6+7;
ll w[n]
;int n,m,bel[n]
;int id[n]
,ps[n]
,l[n]
,r[n]
; ll ans[2]
;int ans[2]
[n];
int sm[n]
;pli f[n]
;void
work
(int o)
;for
(int i=
2;i<=ct;
++i)
f[i]
=std::min(,
);ll tmp=
1e18+7
;int pl=
0,pr=0;
for(
int re i=
1;i++i)
if(ans[o]
>tmp)
for(
int re i=l[pr]
;i<=n;
++i)
if(id[i]
<=m)ans[o]
[++tl]
=id[i]
;for
(int re i=n;i>=l[pr]
;--i)
if(id[i]
>m)ans[o]
[++tl]
=id[i];}
}}void
main()
);work(0
);for(
int re i=
1;i<=n;
++i)w[i]
=-w[i]
; std::
reverse
(id+
1,id+n+1)
;work(1
);bool o=ans[1]
;print
(ans[o]
,'\n');
for(
int re i=
1;i<=n;
++i)
print
(ans[o]
[i],
' ');}
inline
void
file()
signed
main()
主席樹 2012集訓隊互測 Middle
jzoj 2902 集訓隊互測2012 middle 陳立傑 題解 這題雖然不是這幾天做的,但是最近在搞資料結構,再總結一下還是會有收穫的。複習時應該看看 設乙個序列s從大到小排序後為s 1.k 則中位數為m s k 2向上取整 那就意味著,在序列s中,大於等於m的數大於等於k 2。如果把序列s轉化...
集訓隊互測 2012 Attack
description chnlich非常喜歡玩三國志這款遊戲,並喜歡用一些策略出奇制勝。現在,他要開始征服世界的旅途了。他的敵人有n nn座城市和n nn個太守,n nn個城市可以看作在二維平面上的n nn個點。n nn座城市的標號為0,1 2,n 1 0,1,2,cdots,n 1 0,1,2,...
集訓隊互測2015 Robot
題目描述 題解 維護兩顆線段樹,維護最大值和最小值,因為每次只有單點查詢,所以可以直接在區間插入線段就可以了。注意卡常,不要寫stl,用鍊錶把同類修改串起來就好了。pragma gcc optimize 2 pragma gcc optimize 3 include include include ...