日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【nowcoder 224882】牛牛和数组操作(贪心)(剪枝)(区间DP)

發(fā)布時間:2024/3/13 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【nowcoder 224882】牛牛和数组操作(贪心)(剪枝)(区间DP) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

牛牛和數(shù)組操作

題目鏈接:nowcoder 224882

題目大意

給你一個沒有 0 的數(shù)組,每次你可以選一個數(shù),然后把它變成 0,費用是它兩邊為端點最長的沒有 0 的最長區(qū)間的最大值。
然后要你在最小化費用和的情況下,求出方案數(shù)。

思路

首先我們考慮怎樣才會有最大值。

不難發(fā)現(xiàn)每次一定要選當前非 0 0 0 區(qū)間中最大的(因為你要讓最大的貢獻次數(shù)最少)
(這樣子除了一個最大值每個都貢獻一次)

然后你就發(fā)現(xiàn)你分割開之后兩個的順序兩個之間是沒有關(guān)系的,所以如果兩個大小分別是 x , y x,y x,y,那它們后面的組合的方案就是 C x + y x C_{x+y}^x Cx+yx?

然后你可以拿個記憶化,然后 n 2 n^2 n2 個狀態(tài)每次轉(zhuǎn)移 n n n 似乎會超時?

沒錯,但是我們發(fā)現(xiàn)一個點可以優(yōu)化:
如果有最大值連續(xù),那我們就算選的順序不同,那后面的方案數(shù)也是一樣的。
所以我們就可以特判,如果出現(xiàn)最大值連續(xù),那我們就直接在這里分了,然后最大值一邊一個。

然后這樣就變成了 O ( n 2 ) 3 O(\dfrac{n}{2})^3 O(2n?)3
(因為你可以像之前跑的時候最大值的個數(shù)一定不會超過 n 2 \dfrac{n}{2} 2n?

然后就可以過了。

代碼

#include<cstdio> #include<cstring> #include<iostream> #define ll long long #define mo 998244353using namespace std;ll n, maxn[21][2001]; ll a[2001], log2[2001]; ll rem[2001][2001], C[2001][2001];ll get_max(ll l, ll r) {//ST 表求最大值if (l > r) return 0;ll k = log2[r - l + 1];return max(maxn[k][l], maxn[k][r - (1 << k) + 1]); }ll work(ll l, ll r) {if (l == r) return 1;if (l > r) return 1;if (rem[l][r] != -1) return rem[l][r];//記憶化ll maxn = get_max(l, r);ll re = 0;for (ll i = l + 1; i <= r; i++) {//處理有連續(xù)相同的if (a[i] == maxn && a[i - 1] == maxn) {return work(l, i - 1) * work(i, r) % mo * C[r - l + 1][r - i + 1] % mo;}}for (ll i = l; i <= r; i++)//處理普通的分割if (a[i] == maxn) {re = (re + work(l, i - 1) * work(i + 1, r) % mo * C[r - l][r - i] % mo) % mo;}return rem[l][r] = re; }int main() {memset(rem, -1, sizeof(rem));scanf("%lld", &n);for (ll i = 1; i <= n; i++) scanf("%lld", &a[i]), maxn[0][i] = a[i];C[0][0] = 1;//預(yù)處理組合數(shù)for (ll i = 1; i <= n; i++) {C[i][0] = 1;for (ll j = 1; j <= n; j++) {C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mo;}}for (ll i = 1; i <= 20; i++)//ST表預(yù)處理for (ll j = 1; j + (1 << i) - 1 <= n; j++)maxn[i][j] = max(maxn[i - 1][j], maxn[i - 1][j + (1 << (i - 1))]);log2[0] = -1;for (ll i = 1; i <= n; i++)log2[i] = log2[i >> 1] + 1;printf("%lld", work(1, n));return 0; }

總結(jié)

以上是生活随笔為你收集整理的【nowcoder 224882】牛牛和数组操作(贪心)(剪枝)(区间DP)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。