【nowcoder 224882】牛牛和数组操作(贪心)(剪枝)(区间DP)
生活随笔
收集整理的這篇文章主要介紹了
【nowcoder 224882】牛牛和数组操作(贪心)(剪枝)(区间DP)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
牛牛和數組操作
題目鏈接:nowcoder 224882
題目大意
給你一個沒有 0 的數組,每次你可以選一個數,然后把它變成 0,費用是它兩邊為端點最長的沒有 0 的最長區間的最大值。
然后要你在最小化費用和的情況下,求出方案數。
思路
首先我們考慮怎樣才會有最大值。
不難發現每次一定要選當前非 0 0 0 區間中最大的(因為你要讓最大的貢獻次數最少)
(這樣子除了一個最大值每個都貢獻一次)
然后你就發現你分割開之后兩個的順序兩個之間是沒有關系的,所以如果兩個大小分別是 x , y x,y x,y,那它們后面的組合的方案就是 C x + y x C_{x+y}^x Cx+yx?。
然后你可以拿個記憶化,然后 n 2 n^2 n2 個狀態每次轉移 n n n 似乎會超時?
沒錯,但是我們發現一個點可以優化:
如果有最大值連續,那我們就算選的順序不同,那后面的方案數也是一樣的。
所以我們就可以特判,如果出現最大值連續,那我們就直接在這里分了,然后最大值一邊一個。
然后這樣就變成了 O ( n 2 ) 3 O(\dfrac{n}{2})^3 O(2n?)3。
(因為你可以像之前跑的時候最大值的個數一定不會超過 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++) {//處理有連續相同的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;//預處理組合數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表預處理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; }總結
以上是生活随笔為你收集整理的【nowcoder 224882】牛牛和数组操作(贪心)(剪枝)(区间DP)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TypeScript 学习笔记(四)--
- 下一篇: 理解前后端分离概念