動態規劃專題 解題報告 D

2021-09-23 14:06:55 字數 1680 閱讀 6871

我們先來想想n2 怎麼做,兩個n2 迴圈乙個求以i結尾的最長上公升子串行,另乙個逆序求一遍,然後列舉i,以i為中間點的長度,迴圈更新結果就有了。是不是很簡單,恭喜你tle。

想都不用想必t好嗎?

沒有個nlogn演算法怎麼在1e6的資料範圍面前找場子?

nlo

gn

nlogn

nlog

n做法

我們其實不難看出,對於n2

做法而言,其實就是暴力列舉:將每個狀態都分別比較一遍。但其實有些沒有必要的狀態的列舉,導致浪費許多時間,當元素個數到了104-105以上時,就已經超時了。而此時,我們可以通過另一種動態規劃的方式來降低時間複雜度:

將原來的dp陣列的儲存由數值換成該序列中,上公升子串行長度為i的上公升子串行,的最小末尾數值。

這其實就是一種幾近貪心的思想:我們當前的上公升子串行長度如果已經確定,那麼如果這種長度的子串行的結尾元素越小,後面的元素就可以更方便地加入到這條我們臆測的、可作為結果、的上公升子串行中。

但是這樣沒有我們最需要的結果呀,我們要的還是位置資訊。那也很簡單,用二分查詢就能很快地定位到序列的位置,最長的乙個就是以i結尾的上公升子串行。

**(單邊)

for (int i = 2; i <= n; i++)

if (a[i] > low1[len1]) //如果能更新到末位

else //如果在佇列中間

ac**

#include#define for(a, b, c) for(int a=b; a<=c; a++)

#define maxn 1000005

#define maxm 55

#define hrdg 1000000007

#define inf 2147483647

#define llinf 9223372036854775807

#define ll long long

#define pi acos(-1.0)

#define ls p<<1

#define rs p<<1|1

using namespace std;

int n, low1[maxn], a[maxn], f[maxn], b[maxn], low2[maxn];

int f1[maxn], f2[maxn], ans, k[maxn];

int dp2[maxn], dp1[maxn];

inline int read()

while(c>='0'&&c<='9')

return x*f;

}int main()

//正向求一遍

int len1 = 0; low1[++len1] = a[1]; f1[1] = len1;

for (int i = 2; i <= n; i++)

if (a[i] > low1[len1])

else

//for(i, 1, n) printf("%d ", f1[i]-1); coutelse

for (int i = 1; i <= n; i++)

ans = max(ans, min(f1[i], f2[n+1-i])*2-1); //列舉更新

cout

}

動態規劃專題 解題報告 A

乙個經典的貨郎擔問題,加上17的範圍限制各種明示狀態壓縮,用二進位制來表示走過哪幾個城市,我們可以開乙個二維陣列dp i j 表示走過了i的城市,最後在j城市停留的距離。預處理一遍每個城市間的距離,算出dis i j 到dp i j 的狀態可以由 1 1 j k 轉移過來,比較距離儲存最優值就行,然...

動態規劃專題 解題報告 M

別的我不說了,良心題解先吹一波好吧。最重要的使這一段 假如第一位4,第二位7,三四位就可以隨便取了。設這種狀態為 2,2 意思為前兩位已經匹配上了4750的第二位。則用dp 2 2 表示 dp 100010 5 一共5 1e5種狀態 那麼 2,2 就有10種選擇 0 9 會轉移1次到 3,3 選5 ...

動態規劃專題 解題報告 B

首先在從乙個點,目標是向西運輸,那麼它一路走過的路徑x中可能朝西也可能朝北,但最終指向的都是西邊,畫圖可知西方同行中所有的礦點必只能向西運輸,即使是從出發就開始一路向北,最終也只能匯流進路徑x中,指向西。從該點向北的運輸,北方同列的考慮也是一樣的。我們可以預處理出從乙個點向西和向北的貢獻是什麼。我們...