好吧,我承认是sb题QAQ

BZOJ2171弱化版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凹凸序列的更多相关文章

  1. Codeforces 463D Gargari and Permutations(求k个序列的LCS)

    题目链接:http://codeforces.com/problemset/problem/463/D 题目大意:给你k个序列(2=<k<=5),每个序列的长度为n(1<=n< ...

  2. AcWing 334. K匿名序列

    大型补档计划 题目链接 就是把序列分成无数段,每段长度 $ >= K$,然后 \([l, r]\) 这段的花费是 \(S[r] - S[l - 1] - (r - l + 1) * a[l]\) ...

  3. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  4. 求两个有序序列合并成新有序序列的中位数,求第k小数

    此算法涉及一个重要数学结论:如果A[k/2-1]<B[k/2-1],那么A[0]~A[k/2-1]一定在第k小的数的序列当中,可以用反证法证明. 算法思想如下: 1,假设A长度为m,B长度为n, ...

  5. Python数据类型之“序列概述与基本序列类型(Basic Sequences)”

    序列是指有序的队列,重点在"有序". 一.Python中序列的分类 Python中的序列主要以下几种类型: 3种基本序列类型(Basic Sequence Types):list. ...

  6. 寻找数组中的第K大的元素,多种解法以及分析

    遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因 ...

  7. O(n)获得中位数及获得第K小(大)的数

    首先,中位数问题可以归结为求 K=n/2的 第K小元素,并无明显区别. 第一种方法,用MaxHeap,大小为K的大顶堆,能够求出最小的K的元素,复杂度为O(n*logK). 当K较大时,复杂度会较高. ...

  8. hdu5884 Sort(二分+k叉哈夫曼树)

    题目链接:hdu5884 Sort 题意:n个有序序列的归并排序.每次可以选择不超过k个序列进行合并,合并代价为这些序列的长度和.总的合并代价不能超过T, 问k最小是多少. 题解:先二分k,然后在k给 ...

  9. POJ 1094 Sorting It All Out (拓扑排序,判断序列是否唯一,图是否有环)

    题意:给出n个字符,m对关系,让你输出三种情况:     1.若到第k行时,能判断出唯一的拓扑序列,则输出:         Sorted sequence determined after k re ...

随机推荐

  1. IEquatable 的Equals 代替 object 的Equals

    struct Point2 : IEquatable<Point2> { public int X { get; set; } public int Y { get; set; } pub ...

  2. ecshop程序结构说明

    文件夹说明 名称 备注(作用或意义) 根目录 前台程序文件 admin 后台程序文件 admin/help 功能的帮助文件 admin/images 后台页面用图片 admin/includes 后台 ...

  3. 让FineUI数据绑定支持dynamic对象

    FineUI非常好用,但是有一个缺点,就是不支持dynamic对象的数据绑定.查了一下源代码,找了解决方案,其实只需要几行代码就可以搞定,这就是开源的好处. 本想直接在CodePlex上贡献代码,但不 ...

  4. js中,还真不了解 console

    参考链接: https://segmentfault.com/a/1190000000481884

  5. text-indent:2em详解

    text-indent:2em; 解释一下:text的意思是文本,indent在计算机英语中意思是缩进,至于后面的2em意思就是2个相对单位: em又是什么单位? em这个单位的意思就是文字的高度,1 ...

  6. 浅谈JavaScript中的this

    引言 JavaScript 是一种脚本语言,因此被很多人认为是简单易学的.然而情况恰恰相反,JavaScript 支持函数式编程.闭包.基于原型的继承等高级功能.本文仅采撷其中的一例:JavaScri ...

  7. web.config中customErrors与httpErrors的区别

    打开IIS,我们发现会有两个处理错误页的地方,见下图: 进行不同的设置之后,我们发现设定结果会反应在web.config: .NET Error Pages设定被写入system.web/custom ...

  8. Linux 脚本 sh 和 ./ 的区别

    如果.不在PATH里面,要执行当前目录下的可执行文件,使用全路径:./executable-file PATH是环境变量,如果将当前目录“./”添加到环境变量中,那么也可以不用“./”,直接输入当前目 ...

  9. [Json.net]忽略不需要的字段

    摘要 在序列化对象,总会遇到一些敏感的信息,这些信息,并不想对调用接口的用户暴露出来,又或者移动端调用接口的时候,为了不返回没用的信息占用流量,这个时候也需要把一些信息给过滤掉. 系列文章 [Json ...

  10. Kafka入门经典教程

      本帖最后由 desehawk 于 2015-5-3 00:45 编辑问题导读 1.Kafka独特设计在什么地方?2.Kafka如何搭建及创建topic.发送消息.消费消息?3.如何书写Kafka程 ...