好吧,我承认是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. TextView 选择文字

    final CharSequence edit = text2.getText(); text2.setCursorVisible(true); text2.setOnTouchListener(ne ...

  2. 怎样用命令行编译C#程序

    1. 把程序拷贝至记事本 2.另存为*cs格式 3.找到VS2015提供的命令提示 4.要把命令行指向程序所在的目录(可以有个小软件) 如果在其他的盘符,先敲D:,然后再cd 5.输入csc hell ...

  3. Centos 6.0将光盘作为yum源的设置方法

    在使用Centos 的时候,用yum来安装软件包是再方便不过了,但是如果在无法连接互联网的情况下,yum就不好用了. 下面介绍一种方式,就是将Centos安装光盘作为yum源,然后使用yum来安装软件 ...

  4. pyinstaller 官方介绍

    http://www.pyinstaller.org/ pyinstaller支持多个平台,windows,linux,mac,兼容多个第三方包,包括pyqt,django,matplotlib Py ...

  5. Java——不弹起的按钮组件:JToggleButton

    import java.awt.GridLayout; import javax.swing.JFrame; import javax.swing.JToggleButton; //========= ...

  6. 11 Clever Methods of Overfitting and how to avoid them

    11 Clever Methods of Overfitting and how to avoid them Overfitting is the bane of Data Science in th ...

  7. paramiko模拟ansible远程执行命令

    主模块 #!/usr/bin/env python from multiprocessing import Process import paramiko import time import sys ...

  8. Swiper基本上使用

    导入三个文件 jquery-1.11.1.min.js,swiper.min.js,swiper.min.css 攻略教程 http://www.swiper.com.cn/api/function/ ...

  9. 极光推送 JPush 项目简单使用

    打开或者关闭推送 - (void)pushSwitch:(UISwitch *)sender { if (sender.on) { [[NSUserDefaults standardUserDefau ...

  10. Could not load file or assembly Microsoft.Web.Infrastructure

    Error info:Could not load file or assembly 'Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=n ...