題意: 每個數字代表一種顏色, 乙個區間的美麗度為其中顏色的種數, 給出乙個有 n 個元素的陣列, 問將其分成 k 個區間, 問 k 個區間的美麗度和最大為多少 .
思路: dp + 線段樹區間更新, 區間最值
用 dp[i][j] 儲存前 j 個元素分成 i 個區間的最大美麗度和為多少, 那麼動態轉移方程式為:
dp[i][j] = max(dp[i - 1][k] + gel(k + 1, n)), 其中 i <= k <= n, gel(k + 1, n) 表示區間 [k + 1, n] 的美麗度為多少 .
可以用線段樹來維護 dp[i -1][k] + gel(k + 1, n) 的值, 這部分和 裡面的線段樹用法是一樣的. 建樹時將 sum 初始化為上一輪 dp 的結果. 再遍歷 [i, m] 並將 dp 結果記錄一下即可.
**:
1 #include 2 #include 3view code#define lson l, mid, rt << 1
4#define rson mid + 1, r, rt << 1 | 1
5using
namespace
std;67
const
int maxn = 4e4 + 10;8
intpre[maxn], last[maxn], a[maxn];
9int dp[50 + 10][maxn], sum[maxn << 2], lazy[maxn << 2
];10
11void push_up(int
rt)14
15void push_down(int
rt)23}24
25void build(int l, int r, int rt, int
k)31
int mid = (l + r) >> 1;32
build(lson, k);
33build(rson, k);
34push_up(rt);35}
3637
void update(int l, int r, int value, int l, int r, int
rt)43
push_down(rt);
44int mid = (l + r) >> 1;45
if(l <=mid) update(l, r, value, lson);
46if(r >mid) update(l, r, value, rson);
47push_up(rt);48}
4950
int query(int l, int r, int l, int r, int
rt)59
60int main(void)68
for(int i = 1; i <= k; i++)74}
75 printf("
%d\n
", dp[k][n]);
76return0;
77 }
線段樹,區間最值
codeforces 91b queue 線段樹,區間最值 題意是,對於給定區間內的每個元素,要求求出離他最遠的那個元素之間的距離。可以維護乙個線段樹的最小值,每次對於乙個元素,查詢其最右邊的元素的位置。include include include includeusing namespace s...
區間最值與線段樹
區間最值問題 有如下無序序列,求任意子區間段的最大值。接著,我們要用分治的思想來快速地解決上面的問題。在解決問題之前,先介紹一些分治的概念。二分查詢 二分查詢是分治思想的典型運用 我們有如下序列 a1,a2,a3 an.要查詢其中等於b的元素。一種方法就是乙個個對比,看看是不是相等,時間複雜度為n。...
動態區間最值(RMQ) 線段樹
建樹 a aa陣列為初始陣列,tre etree tree 陣列為樹 typedef long long ll const int inf 0x7fffffff const int maxn 2e5 10 int a maxn int tree maxn 2 lz maxn 2 建樹函式 和普通線段...