zoukankan      html  css  js  c++  java
  • [2016湖南长沙培训Day4][前鬼后鬼的守护 chen] (动态开点线段树+中位数 or 动规 or 贪心+堆优化)

    题目大意

    给定一个长度为n的正整数序列,令修改一个数的代价为修改前后两个数的绝对值之差,求用最小代价将序列转换为不减序列。

    其中,n满足小于500000,序列中的正整数小于10^9

    题解(引自mzx神犇的题解)

    本次test跪0了,尴尬

    解法1(40分)

    考虑dp

    设到第i个数为止,序列中数全部<=j的最小代价为f[i][j]

    可以推出f[i][j]=min{f[i-1][j]+|ai-j|,f[i][j-1]}

    解法2(60分)

    是对于第一个dp思路的优化

    既然数字是固定的,可以离散化,降低空间时间复杂度

    解法3(100分)

    斜率优化dp,用线段树维护斜率

    解法4(100分,引自zyz大神的解法)

    玄学的单调栈问题

    由于区间中的数是单调不减的,所以最后得出的序列一定是一段一段的各个数值相等的序列区间

    而要最小化代价,可以取这些区间中的中位数作为标准来修改每个区间,并用单调栈求解最优的区间划分

    还需要用动态开点线段树维护区间中位数

    orz

    #include <stdio.h>
    #include <string.h>
    
    const int MAXN = 5e5 + 10;
    const int INF = 1e9 + 10;
    
    inline int abs(int x){
      return x < 0 ? -x : x;
    }
    
    int Rin(){
      int x = 0, c = getchar(), f = 1;
      for(; c < 48 || c > 57; c = getchar())
        if(!(c ^ 45))
          f = -1;
      for(; c > 47 && c < 58; c = getchar())
        x = (x << 1) + (x << 3) + c - 48;
      return x * f;
    }
    
    namespace Arcueid{
      struct Node{
        Node *l, *r;
        int s;
        Node(){}
        Node(Node *_l, Node *_r, int _s) : l(_l), r(_r), s(_s) {}
      }*_nil = new Node(), *nil = (*_nil = Node(_nil, _nil, 0), _nil), pool[MAXN * 32], *top = pool;
      Node *reborn(){
        *top = Node(nil, nil, 0);
        return top++;
      }
      void death(Node *&pr, Node *pl, int l, int r, int v){
        pr = reborn(); *pr = *pl; pr->s++;
        if(l + 1 < r){
          int mid = (l + r) >> 1;
          v < mid ? death(pr->l, pl->l, l, mid, v) : death(pr->r, pl->r, mid, r, v);
        }
      }
      int secret(Node *pr, Node *pl, int l, int r, int k){
        if(l + 1 == r)return l;
        int c = pr->l->s - pl->l->s, mid = (l + r) >> 1;
        return c < k ? secret(pr->r, pl->r, mid, r, k - c) : secret(pr->l, pl->l, l, mid, k);
      }
      int feel(Node *pr, Node *pl){
        int c = pr->s - pl->s;
        return secret(pr, pl, 0, INF, (c + 1) >> 1);
      }
    }
    
    Arcueid::Node *rt[MAXN] = {Arcueid::nil};
    
    namespace moon{
      void cause(){
        int n, a[MAXN], stay = 1, night[MAXN], shiki[MAXN];
    
        //    freopen("chen.in", "r", stdin);
        //    freopen("chen.out", "w", stdout);
    
        n = Rin();
        for(int i = 1; i <= n; i++){
          a[i] = Rin();
          Arcueid::death(rt[i], rt[i-1], 0, INF, a[i]);
          for(; stay > 1 && Arcueid::feel(rt[i], rt[night[stay - 1]]) < shiki[stay - 1]; stay--);
          shiki[stay] = Arcueid::feel(rt[i], rt[night[stay-1]]);
          night[stay++] = i;
        }
        long long ans = 0;
        for(int i = 1; i < stay; i++)
          for(int j = night[i - 1] + 1; j <= night[i]; j++)
        ans += abs(a[j] - shiki[i]);
    
        printf("%lld
    ", ans);
        //    fclose(stdin);
        //    fclose(stdout);
      }
    }
    
    int main(){
      moon::cause();
      return 0;
    }

    解法5(100分)

    其实这个解法更玄

    但最简洁的往往是最好的

    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    inline int read(){
      int x = 0, c = getchar(), f = 1;
      for(; c < 48 || c > 57; c=getchar())
        if(!(c ^ 45))
          f = -1;
      for(; c > 47 && c < 58; c=getchar())
        x = (x << 1) + (x << 3) + c - 48;
      return x * f;
    }
    
    long long ans = 0;
    priority_queue<int> q;
    
    int main(){
      int n = read();
      for(int i = 1; i <= n; i++){
        int x = read();
        q.push(x);
        ans += q.top() - x;
        if(x ^ q.top())
          q.pop();
      }
      printf("%lld
    ", ans);
      return 0;
    }
  • 相关阅读:
    Grunt VS Gulp
    Gulp开发教程(翻译)
    JavaScript的ajax使用
    移动端交互手势详解及实现
    JavaScript获取页面宽度高度
    JavaScript中的this(你不知道的JavaScript)
    前端Web开发MVC模式-入门示例
    RequireJS实例分析
    JavaScript 模块化历程
    LABjs、RequireJS、SeaJS 哪个最好用?为什么?- 玉伯的回答
  • 原文地址:https://www.cnblogs.com/keshuqi/p/6231334.html
Copyright © 2011-2022 走看看