三類經典應用:
一.區間mex
解題思路:對於主席樹,我們維護一顆權值線段樹,並且用來記錄每乙個數最後出現的位置。為什麼這樣做呢?例如現在有序列[3,
1,0,
2,?,
?]
[3,1,0,2,?,?]
[3,1,0
,2,?
,?],那麼對於主席數來說我們維護[1,
4]
[1,4]
[1,4
]的序列,主席樹內容為[3,
2,4,
1,0,
0]
[3,2,4,1,0,0]
[3,2,4
,1,0
,0],那麼如果我們查詢mex
(2,4
)mex(2,4)
mex(2,
4),也就是說我們需要快速在序列中找到乙個小於2的數並且下標最小,並且最後的下標就是答案,顯然下標為3
33的數為1滿足小於2,那麼最後答案就是3。對於這個尋找過程,我們只需要維護乙個區間min
[x
]min[x]
min[x]
表示區間x[l
,r
]x[l,r]
x[l,r]
最後一次修改的最小位置。[l,
r]
[l,r]
[l,r
]即為答案區間,若[l,
r]
[l,r]
[l,r
]中最小的那個位置小於詢問的l
ll,則答案可能在[l,
r]
[l,r]
[l,r
]內由於答案具有單調性,於是我們在主席樹上二分就可以找到最終解了,如果看不懂,模擬一下**過程也大致能明白
const
int n =
2e5+5;
int n , m;
int a[n]
, lst[n]
, tot;
int rt[n<<5]
, lc[n<<5]
, rc[n<<5]
, minn[n<<5]
;int
insert
(int pre,
int l ,
int r,
int k ,
int val)
int mid =
(l + r)
>>1;
if(k <= mid)
lc[now]
=insert
(lc[pre]
, l, mid, k , val)
;else
rc[now]
=insert
(rc[pre]
, mid +
1, r, k, val)
; minn[now]
=min
(minn[lc[now]
], minn[rc[now]])
;return now;
}int
query
(int i,
int l,
int r,
int val)
intmain
(void
)int len = n +1;
rt[0]
=0;for
(int i =
1; i <= n ; i ++
) rt[i]
=insert
(rt[i-1]
,0, len, a[i]
, i)
;while
(m --
)}
二.區間種類數
解題思路:本題和上乙個題的做法類似,都是要考慮最後乙個數出現的位置,只不過這裡是將位置標記為0or
10or1
0or1
,舉個例子就明白了 。現在假設有序列[3,
5,3,
7,6]
[3,5,3,7,6]
[3,5,3
,7,6
] 詢問你 typ
e(1,
5)
type(1,5)
type(1
,5) 那麼對於主席樹我們維護了5個字首序列[1,
0,0,
0,0]
,[1,
1,0,
0,0]
,[0,
1,1,
0,0]
,[0,
1,1,
1,0]
,[0,
1,1,
1,1]
[1,0,0,0,0],[1,1,0,0,0],[0,1,1,0,0],[0,1,1,1,0],[0,1,1,1,1]
[1,0,0
,0,0
],[1
,1,0
,0,0
],[0
,1,1
,0,0
],[0
,1,1
,1,0
],[0
,1,1
,1,1
],顯然我們求一下第五個序列的區間和就是答案了。這裡的主席樹維護的並不是值域桶而是下標桶(如果維護值域桶,那麼直接對序列做差時間複雜度會出現問題,因為你做差後得到的新序列大於1的數需要作為1計算,這個地方需要遍歷[l,r],和暴力就沒有區別了).至於上面描述過程如何實現,看**模擬一下就知道了。
const
int n =
1e6+5;
int n, m;
int a[n]
, last[n]
, tot;
int rt[n <<5]
, lc[n <<5]
, rc[n <<5]
, sum[n <<5]
;int
insert
(int pre ,
int l ,
int r,
int k ,
int val)
int mid =
(l + r)
>>1;
if(k <= mid)
lc[now]
=insert
(lc[pre]
, l, mid, k , val);if
(k > mid)
rc[now]
=insert
(rc[pre]
, mid +
1, r, k , val)
; sum[now]
= sum[lc[now]
]+ sum[rc[now]];
return now;
}int
query
(int i ,
int l ,
int r,
int l ,
int r)
intmain
(void
) last[a[i]
]= i;
} cin >> m;
while
(m --
)}
樹鏈剖分 複習計畫
應用 一.解題思路 該題需要考慮每條邊給答案帶來的貢獻,通過簡單的畫圖和思考我們可以發現,當乙個節點下有偶數個葉子節點時,該節點到父親節點的邊的貢獻為2,若為奇數則為1,那麼最後的答案為n 2 sig ma d u i mod2 0 n 2 sigma du i mod 2 0 n 2 si gma...
網路流複習計畫
既然是複習網路流,那就不會去做水題了吧233 a.bzoj3996 tjoi2015線性代數 看到題就被嚇壞了2333。線性代數根本沒看完好嗎?然後。md轉個模型就是網路流了 題目大意 給定乙個n n 的矩陣b 和乙個1 n 的行向量c 求乙個1 n 的01矩陣a 使 a b c at 最大 a b...
網路流複習計畫
以前一直沒有刻意去練習過網路流的建圖,相當於完全不會網路流。1 usaco4.2 草地排水drainage ditches 最大流 2 清理雪道 最小流 3 有源匯上下界最大流 有源匯上下界最大流模板題 4 有源匯上下界最小流 有源匯上下界最小流 5 bzoj3698 xww的難題 6 士兵占領 7...