BZOJ2171——K凹凸序列
好吧,我承认是sb题QAQ
这题考试的时候写的我快吐血了QAQ
0、题目大意:给一个序列,你可以随便修改,修改是将一个数+1或-1,一次修改的代价是1,问把这个数修改成x的交叉的上升序列或下降序列的最小代价
1、分析:是不是题目大意就看懵逼了,我们来解释一下,题目的意思就是让你把序列改成这样的
上升一波,下降一波,上升一波……或下降一波,上升一波,下降一波。。。
要求这个波动不能超过k-1
2、解题思路:分成4部分QAQ
a) k=1,直接输出中位数,mdzz.....
b) k=2,去点击题解最开始的链接,水题一道
c) k=3,这个就有一点意思了,我们求出1 -> i的上升的最小代价和下降的最小代价,n -> i的上升最小代价和下降的最小代价
然后这个数据只需要一个拐点,于是我们枚举端点,直接暴力求出答案。。。
d) k<=10,注意到这一波数据的n很小,那么我们可以预处理出l...r的上升和下降的最小代价
然后我们dp... f[i][j][k]表示第i为,已经搞了j波,现在要开始上升还是下降,然后做一个n^2k的sbdp
然后一个智障题就被我们AC了QAQ
#include <cmath>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL int
#define inf 1047483647
int a[100000];
namespace R
{
char Getc()
{
static const int LEN=1<<15;
static char buf[LEN],*S=buf,*T=buf;
if(S==T)
{
T=(S=buf)+fread(buf,1,LEN,stdin);
if(S==T) return EOF;
}
return *S++;
}
int read()
{
static char ch;
static int D;
while(!isdigit(ch=Getc()));
for(D=ch-'0';isdigit(ch=Getc());D=(D<<1)+(D<<3)+ch-'0');
return D;
}
}
using namespace R;
namespace merge_heap{
int ls[100000], rs[100000], value[100000], d[100000];
inline int merge(int x, int y){
if(!x) return y;
if(!y) return x;
if(value[x] > value[y]) swap(x, y);
rs[x] = merge(rs[x], y);
if(d[rs[x]] > d[ls[x]]) swap(ls[x], rs[x]);
d[x] = d[ls[x]] + 1;
return x;
}
inline int top(int x){
return value[x];
}
inline int pop(int x){
return merge(ls[x], rs[x]);
}
inline void init(int x, int y){
ls[x] = rs[x] = 0; value[x] = y; d[x] = 1;
}
}
namespace merge_heap1{
int ls[100000], rs[100000], value[100000], d[100000];
inline int merge(int x, int y){
if(!x) return y;
if(!y) return x;
if(value[x] < value[y]) swap(x, y);
rs[x] = merge(rs[x], y);
if(d[rs[x]] > d[ls[x]]) swap(ls[x], rs[x]);
d[x] = d[ls[x]] + 1;
return x;
}
inline int top(int x){
return value[x];
}
inline int pop(int x){
return merge(ls[x], rs[x]);
}
inline void init(int x, int y){
ls[x] = rs[x] = 0; value[x] = y; d[x] = 1;
}
}
int st[200010], tot;
LL sum_mx[200010], sum_mn[200010], res[200010];
int size[200010];
int heap_size[200010];
LL xl[200010][2][2];
LL cost[1010][1010][2];
LL f[1010][20][2];
int n, k;
inline void solve1(){
using namespace merge_heap;
LL ans = 0;
tot = 0;
for(int i = 1; i <= n; i ++) init(i, a[i]);
for(int i = 1; i <= n; i ++){
st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1;
res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1;
while(tot > 1 && top(st[tot]) > top(st[tot - 1])){
tot --; st[tot] = merge(st[tot + 1], st[tot]);
sum_mx[tot] += sum_mx[tot + 1];
sum_mn[tot] += sum_mn[tot + 1];
heap_size[tot] += heap_size[tot + 1];
size[tot] += size[tot + 1];
res[tot] += res[tot + 1];
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
ans += res[tot];
while(heap_size[tot] > size[tot] / 2 + 1){
sum_mn[tot] += top(st[tot]);
sum_mx[tot] -= top(st[tot]);
st[tot] = pop(st[tot]);
heap_size[tot] --;
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
ans += res[tot];
}
}
xl[i][0][0] = ans;
}
ans = 0;
tot = 0;
for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]);
for(int i = 1; i <= n; i ++) init(i, a[i]);
for(int i = 1; i <= n; i ++){
st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1;
res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1;
while(tot > 1 && top(st[tot]) > top(st[tot - 1])){
tot --; st[tot] = merge(st[tot + 1], st[tot]);
sum_mx[tot] += sum_mx[tot + 1];
sum_mn[tot] += sum_mn[tot + 1];
heap_size[tot] += heap_size[tot + 1];
size[tot] += size[tot + 1];
res[tot] += res[tot + 1];
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
ans += res[tot];
while(heap_size[tot] > size[tot] / 2 + 1){
sum_mn[tot] += top(st[tot]);
sum_mx[tot] -= top(st[tot]);
st[tot] = pop(st[tot]);
heap_size[tot] --;
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
ans += res[tot];
}
}
xl[n - i + 1][1][0] = ans;
}
for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]);
}
inline void solve2(){
using namespace merge_heap1;
LL ans = 0;
tot = 0;
for(int i = 1; i <= n; i ++) init(i, a[i]);
for(int i = 1; i <= n; i ++){
st[++ tot] = i; sum_mn[tot] = a[i]; heap_size[tot] = 1;
res[tot] = 0; sum_mx[tot] = 0; size[tot] = 1;
while(tot > 1 && top(st[tot]) < top(st[tot - 1])){
tot --; st[tot] = merge(st[tot + 1], st[tot]);
sum_mx[tot] += sum_mx[tot + 1];
sum_mn[tot] += sum_mn[tot + 1];
res[tot] += res[tot + 1];
heap_size[tot] += heap_size[tot + 1];
size[tot] += size[tot + 1];
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]);
ans += res[tot];
while(heap_size[tot] > size[tot] / 2 + 1){
sum_mx[tot] += top(st[tot]);
sum_mn[tot] -= top(st[tot]);
st[tot] = pop(st[tot]);
heap_size[tot] --;
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]);
ans += res[tot];
}
}
xl[i][0][1] = ans;
}
ans = 0;
tot = 0;
for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]);
for(int i = 1; i <= n; i ++) init(i, a[i]);
for(int i = 1; i <= n; i ++){
st[++ tot] = i; sum_mn[tot] = a[i]; heap_size[tot] = 1;
res[tot] = 0; sum_mx[tot] = 0; size[tot] = 1;
while(tot > 1 && top(st[tot]) < top(st[tot - 1])){
tot --; st[tot] = merge(st[tot + 1], st[tot]);
sum_mx[tot] += sum_mx[tot + 1];
sum_mn[tot] += sum_mn[tot + 1];
heap_size[tot] += heap_size[tot + 1];
size[tot] += size[tot + 1];
res[tot] += res[tot + 1];
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]);
ans += res[tot];
while(heap_size[tot] > size[tot] / 2 + 1){
sum_mx[tot] += top(st[tot]);
sum_mn[tot] -= top(st[tot]);
st[tot] = pop(st[tot]);
heap_size[tot] --;
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]);
ans += res[tot];
}
}
xl[n - i + 1][1][1] = ans;
}
for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]);
}
inline void solve3(int wt){
using namespace merge_heap1;
LL ans = 0;
tot = 0;
for(int i = wt; i <= n; i ++) init(i, a[i]);
for(int i = wt; i <= n; i ++){
st[++ tot] = i; sum_mn[tot] = a[i]; heap_size[tot] = 1;
res[tot] = 0; sum_mx[tot] = 0; size[tot] = 1;
while(tot > 1 && top(st[tot]) < top(st[tot - 1])){
tot --; st[tot] = merge(st[tot + 1], st[tot]);
sum_mx[tot] += sum_mx[tot + 1];
sum_mn[tot] += sum_mn[tot + 1];
heap_size[tot] += heap_size[tot + 1];
size[tot] += size[tot + 1];
res[tot] += res[tot + 1];
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]);
ans += res[tot];
while(heap_size[tot] > size[tot] / 2 + 1){
sum_mx[tot] += top(st[tot]);
sum_mn[tot] -= top(st[tot]);
st[tot] = pop(st[tot]);
heap_size[tot] --;
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]);
ans += res[tot];
}
}
cost[wt][i][0] = ans;
}
}
inline void solve4(int wt){
using namespace merge_heap;
LL ans = 0;
tot = 0;
for(int i = wt; i <= n; i ++) init(i, a[i]);
for(int i = wt; i <= n; i ++){
st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1;
res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1;
while(tot > 1 && top(st[tot]) > top(st[tot - 1])){
tot --; st[tot] = merge(st[tot + 1], st[tot]);
sum_mx[tot] += sum_mx[tot + 1];
sum_mn[tot] += sum_mn[tot + 1];
heap_size[tot] += heap_size[tot + 1];
size[tot] += size[tot + 1];
res[tot] += res[tot + 1];
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
ans += res[tot];
while(heap_size[tot] > size[tot] / 2 + 1){
sum_mn[tot] += top(st[tot]);
sum_mx[tot] -= top(st[tot]);
st[tot] = pop(st[tot]);
heap_size[tot] --;
ans -= res[tot];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
ans += res[tot];
}
}
cost[wt][i][1] = ans;
}
}
inline void inite(){
for(int wt = 1; wt <= n; wt ++){
solve3(wt);
solve4(wt);
}
}
//0 -> down
//1 -> up
int main(){
n = read(); k = read();
for(int i = 1; i <= n; i ++)a[i] = read();
if(k == 1){
sort(a + 1, a + n + 1);
int o = a[n / 2 + 1];
LL ans = 0;
for(int i = 1; i <= n; i ++) ans += abs(o - a[i]);
printf("%d\n", ans);
}
else if(k == 2){
using namespace merge_heap;
tot = 0;
for(int i = 1; i <= n; i ++) init(i, a[i]);
for(int i = 1; i <= n; i ++){
st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1;
res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1;
while(tot > 1 && top(st[tot]) > top(st[tot - 1])){
tot --; st[tot] = merge(st[tot + 1], st[tot]);
sum_mx[tot] += sum_mx[tot + 1];
sum_mn[tot] += sum_mn[tot + 1];
heap_size[tot] += heap_size[tot + 1];
size[tot] += size[tot + 1];
res[tot] += res[tot + 1];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
while(heap_size[tot] > size[tot] / 2 + 1){
sum_mn[tot] += top(st[tot]);
sum_mx[tot] -= top(st[tot]);
st[tot] = pop(st[tot]);
heap_size[tot] --;
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
}
}
}
LL ans = 0;
for(int i = 1; i <= tot; i ++) ans += res[i];
tot = 0;
for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]);
for(int i = 1; i <= n; i ++) init(i, a[i]);
for(int i = 1; i <= n; i ++){
st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1;
res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1;
while(tot > 1 && top(st[tot]) > top(st[tot - 1])){
tot --; st[tot] = merge(st[tot + 1], st[tot]);
sum_mx[tot] += sum_mx[tot + 1];
sum_mn[tot] += sum_mn[tot + 1];
heap_size[tot] += heap_size[tot + 1];
size[tot] += size[tot + 1];
res[tot] += res[tot + 1];
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
while(heap_size[tot] > (size[tot] / 2 + 1)){
sum_mn[tot] += top(st[tot]);
sum_mx[tot] -= top(st[tot]);
st[tot] = pop(st[tot]);
heap_size[tot] --;
res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]);
}
}
}
LL ans1 = 0;
for(int i = 1; i <= tot; i ++) ans1 += res[i];
ans = min(ans, ans1);
printf("%d\n", ans);
}
else if(k == 3){
LL ans = 1047483647;
solve1();
solve2();
for(int i = 0; i <= n; i ++){
ans = min(ans, xl[i][0][0] + xl[i + 1][1][0]);
ans = min(ans, xl[i][0][1] + xl[i + 1][1][1]);
}
printf("%d\n", ans);
}
else{
inite();
k --;
for(int i = 0; i <= n; i ++){
for(int j = 0; j <= k; j ++){
for(int z = 0; z <= 1; z ++){
f[i][j][z] = inf;
}
}
}
f[0][0][0] = f[0][0][1] = 0;
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= k; j ++){
for(int z = 0; z <= 1; z ++){
for(int w = 0; w < i; w ++){
f[i][j][z] = min(f[i][j][z], f[w][j - 1][z ^ 1] + cost[w + 1][i][z ^ 1]);
}
}
}
}
LL ans = inf;
for(int i = 1; i <= k; i ++) ans = min(ans, min(f[n][i][0], f[n][i][1]));
printf("%d\n", ans);
}
return 0;
}
BZOJ2171——K凹凸序列的更多相关文章
- Codeforces 463D Gargari and Permutations(求k个序列的LCS)
题目链接:http://codeforces.com/problemset/problem/463/D 题目大意:给你k个序列(2=<k<=5),每个序列的长度为n(1<=n< ...
- AcWing 334. K匿名序列
大型补档计划 题目链接 就是把序列分成无数段,每段长度 $ >= K$,然后 \([l, r]\) 这段的花费是 \(S[r] - S[l - 1] - (r - l + 1) * a[l]\) ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 求两个有序序列合并成新有序序列的中位数,求第k小数
此算法涉及一个重要数学结论:如果A[k/2-1]<B[k/2-1],那么A[0]~A[k/2-1]一定在第k小的数的序列当中,可以用反证法证明. 算法思想如下: 1,假设A长度为m,B长度为n, ...
- Python数据类型之“序列概述与基本序列类型(Basic Sequences)”
序列是指有序的队列,重点在"有序". 一.Python中序列的分类 Python中的序列主要以下几种类型: 3种基本序列类型(Basic Sequence Types):list. ...
- 寻找数组中的第K大的元素,多种解法以及分析
遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因 ...
- O(n)获得中位数及获得第K小(大)的数
首先,中位数问题可以归结为求 K=n/2的 第K小元素,并无明显区别. 第一种方法,用MaxHeap,大小为K的大顶堆,能够求出最小的K的元素,复杂度为O(n*logK). 当K较大时,复杂度会较高. ...
- hdu5884 Sort(二分+k叉哈夫曼树)
题目链接:hdu5884 Sort 题意:n个有序序列的归并排序.每次可以选择不超过k个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问k最小是多少. 题解:先二分k,然后在k给 ...
- POJ 1094 Sorting It All Out (拓扑排序,判断序列是否唯一,图是否有环)
题意:给出n个字符,m对关系,让你输出三种情况: 1.若到第k行时,能判断出唯一的拓扑序列,则输出: Sorted sequence determined after k re ...
随机推荐
- js正则匹配浮点数或整数
var pos='point(12.4 -45.423453)';var re = /([+]\d+[.]\d+|[-]\d+[.]\d+|\d+[.]\d+|[+]\d+|[-]\d+|\d+)/i ...
- 9月23日JavaScript作业----子菜单下拉
例题一.子菜单下拉 <style type="text/css"> *{ margin:0px auto; padding:0px} #menu{ width:700p ...
- Java数据库——处理大数据对象
处理大数据对象 CLOB中可以存储海量文字 BLOB中可以存储海量二进制数据 如果程序中要想处理这样的大对象操作,则必须使用PreparedStatement完成,所有的内容要通过IO流的方式从大文本 ...
- CSS学习笔记——简述
CSS3学习的教程来自后盾网 div+css网页标准布局 1>div i>DIV全称是division,意为“区块.分割”,DIV标签是一个无意义的容器标签,用于将页面划分出不同的区域 i ...
- Ctrl+Scroll改变所有Editor的缩放比例 (Code::Blocks)
Settings > Editor > Zooming resizes all editors
- SSL/TLS加密传输与数字证书解读
什么是ssl? secure socket layer(ssl)协议最初由netscape企业发展,现已成为网络用来鉴别网站和网页浏览者身份,以及在浏览器使用者及网页服务器之间进行加密通讯的全球化标准 ...
- [Asp.net mvc]jquery.form.js无刷新上传
写在前面 最近在自己的网盘项目中想用ajax.beginform的方式做无刷新的操作,提交表单什么的都可以,但针对文件上传,就是个鸡肋.在网上查找了发现很多人都遇到了这个问题,大部分都推荐使用jque ...
- High Frequency Trading (整理中...)
什么是高频交易系统 1 交易指令完全是由电脑发送,对市场数据的响应延时在微秒级2 系统有专用的软硬件组成,研发时需要大量的计算机专家级的工作3 系统的硬件需要放在离交易所主机很近的位置,所谓co-lo ...
- caller和callee
我们先来看下caller. caller:返回一个对函数(该函数调用了当前函数)的引用. functionName.caller:functionName对象是所执行函数的名称. 说明 对于函数来说, ...
- css3动画由浅入深总结
阅读目录 一:过渡动画---Transitions 二:Animations功能 三:translate(tx,ty) 四:scale(x,y) 五:rotate(x): 5.1:skew(x,y): ...