有乙個直線,在某乙個時刻有乙個餡餅會出現在一些位置,有它的價值。
乙個人一開始可以站在直線的任意地方,然後他每個時刻可以不移動,或向任意一邊移動乙個單位或兩個單位。
要你求這個人最多能拿多少價值的餡餅。
我們看到這道題,弄出最普通的 dp。
\(f_i\) 為對於前 \(i\) 個餡餅,接住了第 \(i\) 個的最大貢獻。
那就是列舉前面的每個點,還有不列舉,然後首先看能不能從那個點趕到這個點,然後就在可以的裡面找最大值,然後加上這個點的貢獻,就是 \(f_i\) 了。
那我們可以看出這是要餡餅按時間先後順序排序。
而且看能否趕到,就要滿足這個式子:(假設 \(i\) 趕到 \(j\),分別掉到格仔的編號是 \(p_i\) 和 \(p_j\),掉的時間分別是 \(t_i\) 和 \(t_j\))
\(abs(p_i-p_j)\leq 2\times(t_j-t_i)\)
總的來說,就是這個:
\[f_j=\max_(p_i-p_j)\leq 2\times(t_j-t_i)}\
\]但是這樣會超時,那我們考慮優化看餡餅的先後順序的地方,看能不能通過這個先後順序,直接快速地找到滿足的點。
那我們考慮把式子化開,因為有絕對值,所有會有兩個式子:
\(\left\
2\times t_i+p_i\leq 2\times t_j+p_j&(p_i-p_j> 0)\\
2\times t_i-p_i\leq 2\times t_j-p_j&(p_i-p_j\leq 0)
\end\right.\)
那它要分開兩種,就很麻煩,我們但其實我們會發現,如果要的那個式子滿足了,另乙個也會滿足。
那我們不妨讓這兩個式子都要滿足。
那我們看怎麼快速地找呢?
首先,因為兩個式子的左右兩邊其實分別是 \(i,j\) 點的兩個值,那我們可以一開始就算出來。
那我們考慮先按乙個排好序,然後就只用判斷另乙個條件就可以了。
但是直接判斷還是不行。
那我們考慮用一些資料結構來優化它。
那我們排好序之後,就要判斷另乙個值的大小關係。那只要大小關係,我們就可以把它離散化,不然值太大,陣列裝不下。
那離散化之後,怎麼看大小呢?
我們想想,從小到大排序之後,意思就是可以從前面走到後面(當然這裡是假設第二個條件都滿足),那你現在就還要看第二個條件。
那就是當兩個值,如果第乙個值的位置比第二個值的位置靠前,而且第乙個位置的第二個比較的值小於第二個值的第二個比較的值。那就是可以的。
你會發現它就是乙個順序對。
順序對逆序對的這些玩意兒,自然就是樹狀陣列。
當然,你用線段樹也不是不可以,但是畢竟樹狀陣列簡單好打嘛。
(記得這個地方的位址是第二個匹配的值,因為樹狀陣列位址其實就是乙個匹配大小的東西,那就應該是最大貢獻)
不過這個樹狀陣列不是求逆序對個數或順序對個數,而是在滿足條件的地方取最大值。
那我們只要改一下,改成維護最大值即可。
那你就可以找到當你弄 \(f_i\) 的時候,最優是從**轉移過來。
那至於 \(f_i\),就是最優還要加上拿到它這個餡餅能有的價值。
至於最後輸出什麼,就是所有最後結束的地方的最大值。那就是查詢 \(1\sim num\) 中樹狀陣列的最大值。(\(num\) 是離散化之後,有多少個不同的第二個匹配的值)
其實就是看找到最後選了**作為結尾使得價值最大。
那就是這樣了。
#include#include#includeusing namespace std;
struct pie a[100001], b[100001];
int w, n, c[100001], now;
int tree[100001], re;
void add_num(int now, int addnum)
int quest(int now)
bool cmp1(pie x, pie y)
bool cmp2(pie x, pie y)
int main()
sort(b + 1, b + n + 1, cmp2);
c[1] = ++c[0];
a[b[1].num].r = c[1];//離散化(對於我們第二個要比較的值)
for (int i = 2; i <= n; i++)
sort(a + 1, a + n + 1, cmp1);//先按第乙個要比較的值排序,使列舉過去的時候第乙個直接符合
for (int i = 1; i <= n; i++)
printf("%d", quest(c[0]));//掃一遍全部,看全部方案中價值最大的
return 0;
}
ybt金牌導航1 1 2 乘坐電梯
有乙個電梯,有 n 個人要進電梯。對於每一秒,排在最前面的人有 p 的機率會進電梯 不會再出來 否則不進,別的人都不進。問你 t 秒後,在電梯上的人的期望數量。這道題我們先設 fi,jf fi,j 為在第 i ii 秒之後有 j jj 個人在電梯上的概率。那首先初始化很顯然,f0,0 1f 1 f0...
ybt金牌導航6 1 1 第 k 小數
求序列中第 k 小的數。不能 nlogn 做。這道題可以用分治來做,分治有點二分的味道。它每次選乙個數列中的數,然後把比它大的放在前面,比它小的放在後面,然後它放在中間。這個你可以搞兩個指標來搞,每次找到兩邊然後 swap 那它的位置就是它的排名 你也只確定了它的,但是夠了 然後如果排名就是你要的,...
ybt金牌導航8 6 5 最小原根
給出乙個質數 p pp,找他最小的原根。不知道原根的可以看這個 點我 至於找原根,其實我們可以用乙個近似暴力的方法找。為什麼可以呢,因為它原根分布廣,而且最小的也比較小。我們就考慮判斷乙個數是否是原根。對於要檢查 g gg 是不是模 p pp 的原根,我們可以列舉 p varphi p p 的質因子...