zoukankan      html  css  js  c++  java
  • HDU 4923 Room and Moor (单调栈)

    题意:

      给你一个A数列,让你求一个单调递增的B数列(0<=bi<=1),使得sum{(ai-bi)^2}最小。

    思路:

      很明显,如果A = 0...01...1,那么bi=ai即可。

      可以证明,如果 A = 1...10...0,那么所有bi达到同一个值的时候取得最优值。 假设 ai = 1, aj = 0, 那么 i<j ,所以bi<=bj。 若bi != bj,那么增大bi的值,或者减小bj的值都可以得到更优的结果。 所以,bi=bj。

      所以,如果A数列里面出现了形如 "1...10...0"的部分,我们都可以把它当做同一段处理。因为他们对应的bi值一定相同。

      这样,我们可以得到一个中间序列,x1, ..., x1, x2, ..., x2, ..., xm, ...xm. 我们可以把它简化为,x1, ..., xm。其中 xi对应着每一段的最优值。

      我们可以发现,这里的xi不一定单调递增。 然后我们仿照上面的证明,知道当有相邻两段的xi递减时,会在他们所有的bi相等时取得最优值。因此,我们可以把这两段合并,求出一个满足单调性的值。

      所以,最后的B序列一定是这样:y1, ..., y1, ..., ym, ..., ym。所以我们可以用一个单调栈来维护所有的bi值。

    代码:

      

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cmath>
     6 #include <algorithm>
     7 #include <string>
     8 #include <queue>
     9 #include <stack>
    10 #include <vector>
    11 #include <map>
    12 #include <set>
    13 #include <functional>
    14 #include <time.h>
    15 
    16 using namespace std;
    17 
    18 typedef pair<double, int> PDI;
    19 
    20 const int INF = 1<<30;
    21 const int MAXN = (int) 1e5+7;
    22 
    23 int n;
    24 int a[MAXN];
    25 double b[MAXN];
    26 
    27 PDI sk[MAXN]; //
    28 int tail; //栈顶指针
    29 
    30 void solve() {
    31     tail = 0; //栈初始化
    32 
    33     for (int i = 0; i < n; i++) {
    34         sk[tail++] = make_pair(1.0*a[i], 1); //当前点入栈
    35         while (tail>1 && sk[tail-1].first<=sk[tail-2].first) { //如果栈不满足单调性,合并最上面两个节点
    36             int cnt = sk[tail-1].second+sk[tail-2].second;
    37             double tmp = (sk[tail-1].first*sk[tail-1].second+sk[tail-2].first*sk[tail-2].second)/cnt;
    38             sk[tail-2] = make_pair(tmp, cnt);
    39             tail--;
    40         }
    41     }
    42     //求出bi
    43     for (int i = 0, j = 0; i < tail; i++)
    44         for (int k = 0; k < sk[i].second; k++)
    45             b[j++] = sk[i].first;
    46     //求出结果
    47     double ans = 0;
    48     for (int i = 0; i < n; i++)
    49         ans += (a[i]-b[i])*(a[i]-b[i]);
    50     printf("%f
    ", ans);
    51 }
    52 
    53 int main() {
    54     #ifdef Phantom01
    55         freopen("HDU4923.txt", "r", stdin);
    56     #endif //Phantom01
    57 
    58     int T;
    59     scanf("%d", &T);
    60     while (T--) {
    61         scanf("%d", &n);
    62         for (int i = 0; i < n; i++)
    63             scanf("%d", &a[i]);
    64         solve();
    65     }
    66 
    67     return 0;
    68 }
    HDU 4923
  • 相关阅读:
    Collectors.reducing总结
    Ubuntu 换源看这一篇就够了
    基于Vue2和Node.js的反欺诈系统设计与实现
    Flink源码解析(四)——从Flink集群部署和任务提交模式看Flink任务的核心组件
    SaaS架构(二) 多租户数据隔离方案
    网络IO模型(BIO,NIO,AIO)
    Gale-Shapley算法
    Java 内存模型
    上位机那些事儿
    三菱PLC之SLMP协议报文说明
  • 原文地址:https://www.cnblogs.com/Phantom01/p/3899429.html
Copyright © 2011-2022 走看看