奇技淫巧訓練之五

2022-01-29 09:17:03 字數 2227 閱讀 8752

這道題真的很好,寫題解的人寫的也真好

如果要保留 a[i],a[i] 和 a[j],a[j] ,

前提是:他們中間的數本身就合法,或者他們中間的數可以被改成合法。

比如,17,50,50,50,19這個序列,看上去17和19能保留,但如果保留,中間三個50怎麼改都不會單調上公升。

可見只有 a[j],a[j] 和 a[i],a[i] 的差大於等於j-i才允許同時保留兩者,否則中間一定出錯。

a[j] - a[i] >= j - i移項:

a[j] - j >= a[i] - i此為保留條件。

所以把根據 a 預處理出新序列 b[i] = a[i] - i,

然後找 b的最長不下降子串行的長度,就是最多能保留的個數。

把 a變成嚴格單調上公升序列等同於:在 b 上對應地處理,並把 b 變成單調不降。

現在就考慮 b怎麼改才能代價最小。

注意:(一) b 的最長不下降子串行可能有多個。

(二) b 的最長不下降子串行中,任何兩個相鄰的元素 b[i], b[j]

(相鄰指的是在子串行中相鄰,而在 b 中不一定相鄰) 之間

,絕對不存在另乙個大小介於兩者之間的元素。

否則取這個元素,保證合法,而且可以使不降序列更長。

所以每個被保留的 b[i]和 b[j] 之間的元素全部不合法。怎麼改變這兩者之間的元素?

黑線表示修改以後的海拔。顯然所有方法都是階梯(橫線看作台階)。此方法看上去很糟。

如果台階上的「上公升點數目」大於「下降點數目」,那麼把台階下降(以滿足那麼多「上公升點」的要求!),

直到它下降到和左邊台階一樣高,也就和左邊變成了同一塊台階。

反之,就把台階上公升到和右邊台階一樣高。然後繼續縮減台階。

如果有up = down的,則台階向上向下都可以(代價不變,台階數目減少)。

這個過程始終保證合法、保證代價減小或不變

這樣變化到end,一定只剩下兩塊台階,左邊的高 b[i],右邊的高 b[j] 。

以上說明,最優解一定是(或者說,一定可以是)

左邊 b[i] to b[k] 全部變成 b[i] 且

右邊 b[k+1] to b[j] 全部變成 b[j]

的形態。

如果最優解不是這樣,我們可以無償甚至減償來變成這種形態

每個區間的 k可以列舉。

code by std

#include #include #include inline int getint()

#define re register

#define ll long long

#define inf 2147483647

inline ll min(ll x, ll y)

inline ll abs(ll x)

int n;

int a[40010], b[40010];

int minof[40010], len = 0, longest[40010];

int first[40010], to[40010], nxt[40010], cnt = 0;

ll f[40010];

ll suml[40010], sumr[40010];

inline void adde(int u, int v)

int main()

if(l == len)

++len;

longest[i] = l+1;

adde(longest[i], i);

minof[l+1] = b[i];

}adde(0, 0);

printf("%d\n", n-(len-1));

memset(f, 20, sizeof(f));

b[0] = -inf;f[0] = 0;

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

}printf("%lld\n", f[n+1]);

return 0;

}

C 之奇技淫巧

typedef struct data 0 pdata 0 typedef struct data 1 pdata 1 結構體data 0與data 1在性質上沒有什麼不同,它們的size是相等的,都是8.但在用法上有很大區別。例 pdata 0 stack0 pdata 0 malloc max ...

git 奇技淫巧

例如 1.0.0 git tag a 1.0.0 m 1.0.0 版本的備註資訊.複製 git push origin tags 複製 例如 1.0.0 git tag d 1.0.0 複製 刪除遠端標籤需要先刪除本地標籤,再執行下面的命令 git push origin refs tags 1.0...

c 的奇技淫巧

關於陣列 數論演算法技巧 stl其他 while scanf d d n,m eof 等價於 while scanf d d n,m 2 前者eof為檔案結束符,較保險 後者 後的數字為輸入的變數的個數 不能只寫while scanf d d n,m 這樣無法結束讀入 wwq大佬教的,希望我不要和他...