貪玩 van 藍月

2021-10-24 19:34:07 字數 2383 閱讀 9053

最窄的題目描述。。。

這是不可能有的

首先需要發現乙個性質,如果現在已經求出k的答案,那麼k+2的答案序列就一定是在k的答案序列中插入兩個(可以是末尾與開頭) 數所得到,至於為什麼,其實我也不知道,那麼考慮k+2的轉換,考慮cdq

假設對於k,在區間l-mid選了k1個點,mid+1-r選了k2個點

那麼對於k+2,就有一下情況:

1.在區間l-mid選k1+1個點,mid+1-r選k2+1個點

2.在區間l-mid選k1個點,mid+1-r選k2+2個點

3.在區間l-mid選k1+2個點,mid+1-r選k2個點

但是由於它是加減加減的,所以還要維護最大值和最小值

cdq分治是解決用乙個子問題來計算對另乙個子問題的貢獻的演算法,所以這道題可以剛好使用,因此dp也可以用此來優化

#includeusing namespace std;

const int maxn = 1e5 + 3;

int n , a[maxn] , f[maxn][23][2];

int w[maxn][2];

void cdq( int l , int r , int step )

int mid = ( l + r )>> 1;

cdq( l , mid , step + 1 );

cdq( mid + 1 , r , step + 1 );

for( int i = l ; i <= r ; i ++ )

f[i][step][1] = 0x3f3f3f3f , f[i][step][0] = -0x3f3f3f3f;

int k1 = 0 , k2 = 0;

if( f[l][step+1][0] > f[mid+1][step+1][0] ) f[l][step][0] = f[l][step+1][0] , k1 = 1;

else f[l][step][0] = f[mid+1][step+1][0] , k2 = 1;

for( int i = l + 2 ; i <= r ; i += 2 )

if( l + k1 + 1 <= mid && mid + k2 <= r && k1 + 2 + k2 == i - l + 1 )

if( l + k1 - 1 <= mid && mid + k2 + 2 <=r )

if( tmp > f[i][step][0] ) f[i][step][0] = tmp , k11 = k1 , k22 = k2 + 2;

}k1 = k11 , k2 = k22;

}k1 = 0 , k2 = 0;

for( int i = l + 1; i <= r ; i += 2 )

if( l + k1 + 1 <= mid && mid + k2 <= r && k1 + 2 + k2 == i - l + 1 )

if( l + k1 - 1 <= mid && mid + k2 + 2 <=r )

if( tmp > f[i][step][0] ) f[i][step][0] = tmp , k11 = k1 , k22 = k2 + 2;

}k1 = k11 , k2 = k22;

}k1 = 0 , k2 = 0;

if( f[l][step+1][1] < f[mid+1][step+1][1] ) f[l][step][1] = f[l][step+1][1] , k1 = 1;

else f[l][step][1] = f[mid+1][step+1][1] , k2 = 1;

for( int i = l + 2 ; i <= r ; i += 2 )

if( l + k1 + 1 <= mid && mid + k2 <= r && k1 + 2 + k2 == i - l + 1 )

if( l + k1 - 1 <= mid && mid + k2 + 2 <=r )

if( tmp < f[i][step][1] ) f[i][step][1] = tmp , k11 = k1 , k22 = k2 + 2;

}k1 = k11 , k2 = k22;

}k1 = 0 , k2 = 0;

for( int i = l + 1 ; i <= r ; i += 2 )

if( l + k1 + 1 <= mid && mid + k2 <= r && k1 + 2 + k2 == i - l + 1 )

if( l + k1 - 1 <= mid && mid + k2 + 2 <=r )

if( tmp < f[i][step][1] ) f[i][step][1] = tmp , k11 = k1 , k22 = k2 + 2;

}k1 = k11 , k2 = k22;

}}int main()

4306 貪玩藍月

題目描述 貪玩藍月 是目前最火爆的網頁遊戲。在遊戲中每個角色都有若干裝備,每件裝備有乙個特徵值 w ww 和乙個戰鬥力 v vv 在每種特定的情況下,你都要選出特徵值的和對 p pp 取模後在一段範圍內的裝備,而角色死亡時自己的裝備會爆掉。每個角色的物品槽可以看成乙個雙端佇列,得到的裝備會被放在兩端...

題解 貪玩藍月

題目傳送門 給出一種元素 u,w 表示它的特徵值為 u 戰鬥力為 w 現在給你乙個雙端佇列,維護該元素,支援兩端加點刪點,以及查詢特徵值之和 pmod p 在 l,r 之內的戰鬥力之和最大的子串行。設操作次數為 m 則保證 m le 5 times 10 4,p le 500 因為懶 菜 得 不 一...

雅禮集訓 2018 Day10 貪玩藍月

點這裡看題目。離線的話,我們顯然可以 線段樹分治 dp 時間複雜度大概是 o m log 2m mp 顯然我們需要乙個 dp 去維護答案,這裡不再贅述。考慮我們直接處理的難點之一是雙端佇列兩段可操作,而一端可操作的結構,棧,就可以簡單地維護 dp 因此,我們考慮將雙端佇列拆成兩棧分別維護左端和右端。...