2018浙江省賽 括號序列

2021-08-19 18:54:04 字數 1544 閱讀 7130

你有 n 個元素排成一行,每個元素都由乙個括號 (左括號或右括號) 和乙個權值構成,我們將第 i 個元素記作(si; vi),其中 si 為 「(」 或者 「)」,vi 為乙個整數 (可能為負數)。

你每次可以選擇一對相鄰的元素,對應的括號為 「()」,即找到乙個 k(1 k < n),滿足 sk 為 「(」 且 sk+1 為「)」。你可以交換第 k 和 k + 1 個元素 (包括括號和對應的權值),然後獲得 vk vk+1 的分數。

現在給你初始的元素排列,問你最多能獲得多少的分數。

如果所有數都》0的話,那貪心把所有)都移到最左邊就好了,但是這裡有負數。

首先可以發現

1.答案只取決於原始狀態和最終狀態[可以確定每個')'跨越了幾個'(']

2.原序列中乙個右括號右邊的右括號不可能向左移時跨越它

所以dp[i][j]表示到左數第i個『)』時,最終將它放在第j個『(』後面,最大收益多少

看起來好像要列舉dp[i-1][k](0<=k<=j),發現每次轉移都是dp[i-1],[0-j]+v[j--當前『(』數量],這樣可以維護字首最大值和字首和優化一下,把dp轉移降到o(1)

#include#include#include#define ll long long

using namespace std;

char s[2020];

ll dp[2020][2020],a[2020],sum[2200];

int len,n,m;

ll max(ll a,ll b)

void work()

for (i=1;i<=len;i++)

scanf("%lld",&a[i]);

for (i=1;i<=len;i++)

n++;

for (j=0;j<=m;j++)

for (j=m+1;j<=mz;j++) dp[n][j]=dp[n][j-1];//以後轉移要用

} cout<>num;

while (num--) work();

}

dp[i][j]只從dp[i-1][j]轉移過來,雖然本題空間不需要優化,但我們發現可以優化掉一維,這樣的話dp陣列需要初始化

#include#include#include#define ll long long

using namespace std;

char s[2020];

ll dp[2020],a[2020],sum[2200];

int len,n,m;

ll max(ll a,ll b)

void work()

for (i=1;i<=len;i++)

scanf("%lld",&a[i]);

for (i=1;i<=len;i++)

n++;

for (j=0;j<=m;j++)

for (j=m+1;j<=mz;j++) dp[j]=dp[j-1];

} cout<>num;

while (num--) work();

}

2018 浙江省賽j zoj4033

本題大意 給你一串數字1為男 0為女 隨著位數增加每個人擁有的寶石數遞增 從一開始 要把這些人分為4組 組 1 2為女 組3 4 為男 並且1 3之和 要等於 2 4之和 解法 總值 2 1的話就無法均分 輸出 1 可以的話 從中值開始 貪心一下 取得到就判斷男女 男的就分到3 女的就分到1 不能取...

2015浙江省賽

zoj 3872 beauty of array 對於每個數,計算這個數被累加的次數。找到這個數左邊這個數出現的地方,在這之間的所有數的數量 這個數後面的數的數量,即為這個數被計算的次數 include include typedef long long ll int a 1000005 post ...

2019浙江省賽

題意 n個點的二叉樹 無向邊 的單向邊,構造一條到達且只到達每個點一次的路徑。題解 兩次dfs。第一次dfs為向i 1優先,2i次之。然而,發現某些點有兩條出路,這是由於該點在最底層 有些點沒有達到,這是因為這些點在最後一層或倒數第二層的右下角 第二次dfs時先判斷該點的右子節點是否達到過,如果沒到...