codeforces round721 div2. E
给n(n<=35000)个数,要求分成k(k<=100)个区间。每个区间当中如果有多个相同的数,那么答案就会加上这个数最后一个减去最前一个的位置。要求划分后答案最小的值是多少。
最近四边形优化做的有点多,下意识觉得可以用决策单调性,但是想想好像不太能够存的下(可能要用一些比较高级的数据结构),看了其他人的代码,发现都是用的线段树。
首先写出dp方程:,
然后我们考虑a[j]对于答案的贡献,假设a[j]上一次出现的位置是pre[j]:
1. a[j]在区间(pre[j] + 1,j)没有出现过:
2. a[j]在区间(1,pre[j])出现过,
这就相当于,在的基础上,在做了一次区间加法。而最小值也要从这一段求出来,所以每一次初始化线段树的值为,然后每一次求的时候,就通过区间加法来获得的值,之后询问区间最小值即可。
复杂度
const int N = 35010, K = 110, inf = 1e9;
int a[N], dp[N][K], pre[N], last[N];struct tree
{int l, r, mn, lazy;
};
tree t[N << 2];void buildtree(int l, int r, int x, int k)
{t[x].l = l; t[x].r = r; t[x].lazy = 0;if (l == r) t[x].mn = dp[l - 1][k];else{int mid = (l + r) >> 1;buildtree(l, mid, x << 1, k);buildtree(mid + 1, r, x << 1 | 1, k);t[x].mn = min(t[x << 1].mn, t[x << 1 | 1].mn);}
}void pushdown(int x)
{t[x << 1].mn += t[x].lazy;t[x << 1].lazy += t[x].lazy;t[x << 1 | 1].mn += t[x].lazy;t[x << 1 | 1].lazy += t[x].lazy;t[x].lazy = 0;
}void change(int l, int r, int x, int d)
{if (l <= t[x].l && t[x].r <= r){t[x].mn += d;t[x].lazy += d;return;}if (l > t[x].r || r < t[x].l)return;pushdown(x);change(l, r, x << 1, d);change(l, r, x << 1 | 1, d);t[x].mn = min(t[x << 1].mn, t[x << 1 | 1].mn);
}int search(int l, int r, int x)
{if (l <= t[x].l && t[x].r <= r)return t[x].mn;if (l > t[x].r || r < t[x].l)return inf;pushdown(x);return min(search(l, r, x << 1), search(l, r, x << 1 | 1));
}int main()
{int T = 1;//T = read();while (T --){int n, k;n = read(); k = read();for (int i = 1; i <= n; i ++){a[i] = read();if (last[a[i]])dp[i][1] = dp[i - 1][1] + i - last[a[i]];elsedp[i][1] = dp[i - 1][1];pre[i] = last[a[i]];last[a[i]] = i;}for (int j = 2; j <= k; j ++){dp[0][j - 1] = inf; buildtree(1, n + 1, 1, j - 1);
// for (int k = 1; k <= n; k ++)
// printf ("%d ", search(k, k, 1));
// printf ("\n");for (int i = 1; i <= n; i ++){change(1, pre[i], 1, i - pre[i]);dp[i][j] = search(1, i, 1);
// for (int k = 1; k <= n; k ++)
// printf ("%d ", search(k, k, 1));
// printf ("\n");}}cout << dp[n][k];}return 0;
}
codeforces round721 div2. E相关推荐
- codeforces#320(div2) D Or Game 贪心
codeforces#320(div2) D "Or" Game 贪心 D. "Or" Game time limit per test 2 seconds ...
- codeforces 628.div2
# Codeforces 628.div2 A. EhAb AnD gCd B. CopyCopyCopyCopyCopy C. Ehab and Path-etic MEXs D. Ehab the ...
- codeforces#324(div2) E. Anton and Ira 贪心
codeforces#324(div2) E. Anton and Ira 贪心 E. Anton and Ira time limit per test 1 second memory limit ...
- codeforces 712 div2 ABC
codeforces 712 div2 ABC A. Déjà Vu A palindrome is a string that reads the same backward as forward. ...
- codeforces round div2,3周赛补题计划(从开学到期末)
1. 本学期场次 从2020.09.19-2021.01.18,一共18周. 题号 场次 日期 备注 1475 Codeforces Round #697 (Div. 3) 1.25 1474 Cod ...
- Codeforces#371 Div2
这是一场非常需要总结的比赛,交了3题,最后终测的时候3题全部没过,一下掉到了绿名,2333 Problem A 题意:给定区间[l1,r1],[l2,r2],然后给定一个整数k,求区间当中相交的元素, ...
- 【Codeforces #130 Div2】Solutions
[208A Dubstep] http://codeforces.ru/problemset/problem/208/A 题目大意:一个句子被添加了若干"WUB",问原句. 将W ...
- 付忠庆的练习小笔记-Codeforces #277 Div2 C
原题链接 http://codeforces.com/contest/486/problem/C 这个C题显然更水一些 步数可以分为两种 上下一种 左右一种 总步数最小 = 上下最小+左右最小 先讨论 ...
- 付忠庆的练习小笔记-Codeforces #276 Div2 C
原题链接 http://codeforces.com/contest/485/problem/C 题意:给出一个区间 l~r 求这个区间内的数中转换成2进制含'1'最多的数,若有多组解,则输出最小的那 ...
最新文章
- 03-MySQL多表操作
- shell 命令执行结果判断语句
- 100 计算机网络概述小结
- PingInfoView批量PING工具
- (转)LUA与python根本就不具有可比性
- Java实现的基于socket的一次通信
- 二十一天学通C语言:C语言中指针排序
- excel文件下载下来损坏 js_js实现txt/excel文件下载
- 2021WordPress转z-blog搬家教程_WordPress搬家zblog博客程序工具
- 用eviews建立sarima模型_计量经济学第10讲(时间序列计量经济学模型:序列相关性)...
- nginx的cgi模块
- ecosphere是什么意思_ecosphere的翻译_音标_读音_用法_例句 - 必应 Bing 词典
- python:tushare 获取A股指数数据,并使用LSTM预测
- 我的awk常用命令备忘 xargs备忘
- Thompson Sampling(汤普森采样)
- 渗透测试-11种绕过CDN查找真实IP的方法
- 如何监控Redis性能指标(译)
- epoll的反应堆实现模式
- ERP 系统,编译和学习
- android百度地图的点击事件监听,百度地图监听事件addEventListener无效