題解 ZJOI2013螞蟻尋路

2022-02-27 13:31:43 字數 1514 閱讀 7581

這題強呀……打了10+30暴力之後苦想1h並不會做……於是去看題解。看題解的時候又莫名各種看錯,結果看了好久才懂……記錄一下血淚史吧。

這題不難發現走出來的圖形就是乙個高低高低的城堡型圖案,命名為高峰跟低谷的話就是一共有k個低谷和k + 1個高峰,且交替出現。發現其實這個圖形是由2 * k + 1個矩形所構成的,我們考慮將這樣許多矩形看做轉移的方向:f[i][j][p][h]代表以點(i, j)為左下角,當前列舉到的是第p個矩形,且高度為(i - h + 1)所能獲得的最大權值。

轉移方程:

\(f[i][j][p][h] = \left \ + s[j][i] - s[j][h - 1]; \)

其中第一部分代表和j - 1處於同乙個矩形當中,第二部分則表示根據p的奇偶性選擇\( ans = max(f[i][j][k][i], g[i][j][k][i][0]); \)

起初並沒有很理解為什麼要將前一部分考慮進來。當高度等於i,不是說明這是乙個低谷嗎?為什麼會符合條件呢?但其實有一種情況下是可以的:當沒有低谷的時候,這樣是乙個符合條件的解。追加輔助陣列的dp做的太少了,要多多加油呀ヾ(๑╹◡╹)ノ"

#include using

namespace

std;

#define inf 999999999

#define maxn 105

int n, m, k, ans = -inf, sum[maxn][maxn];

int f[maxn][maxn][maxn], g[maxn][maxn][maxn][2

];int

read()

while(c >= '

0' && c <= '

9') x = x * 10 + c - '

0', c =getchar();

return x *k;}

void

work()

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

for(int j = 1; j <= m; j ++)

g[j][p][

1][0] = -inf;

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

g[j][p][h][

0] = max(g[j][p][h - 1][0], f[j][p][h - 1

]); g[j][p][i][

1] = -inf;

for(int h = i - 1; h >= 1; h --)

g[j][p][h][

1] = max(g[j][p][h + 1][1], f[j][p][h + 1

]); }

ans = max(ans, max(f[j][k][i], g[j][k][i][0

]));

}}int

main()

work();

printf(

"%d\n

", ans);

return0;

}

K大數查詢 ZJOI2013

題目描述 你需要維護 n 個可重整數集,集合的編號從 1 到 n 這些集合初始都是空集,有 m 個操作 輸入 輸出格式 不關心 1 le n,m le 5 times 10 4 1 le l,r le n 1 操作中 c le n 2 操作中 1 le c 2 暴力樹套樹 外層維護權值線段樹 內層是...

BZOJ K大數查詢(分治)(Zjoi2013)

有n個位置,m個操作。操作有兩種,每次操作如果是1 a b c的形式表示在第a個位置到第b個位置,每個位置加入乙個數c 如果是2 a b c形式,表示詢問從第a個位置到第b個位置,第c大的數是多少。第一行n,m 接下來m行,每行形如1 a b c或2 a b c 輸出每個詢問的結果 題目大意 略。思...

題解 P3332 ZJOI2013 K大數查詢

link 你需要維護 n 個可重整數集,集合的編號從 1 到 n 這些集合初始都是空集,有 m 個操作 1 leq n m leq 10 5 1 leq c leq 2 發現插入,查詢 k 大,考慮線段樹套平衡樹。但是發現 n m leq 10 5 並且區間插入並不好打懶標記,比較麻煩。並且因為平衡...