zoukankan      html  css  js  c++  java
  • bzoj 2216 Lightning Conductor

    题目传送门

      需要root权限的传送门

    题目大意

      给定一个长度为$n$的数组,要求对每个$1 leqslant i leqslant n$找到最小整数的$p$,对于任意$j$满足使得$a_{i} + p - sqrt{left | i - j ight |} geqslant a_{j}$。

      一来想到函数$y = left lceil sqrt{x} ight ceil$,至多有根号个取值,然后发现$O(nsqrt{n})$会稳T。

      对于函数$y = sqrt{x}$有一些很优美的性质,比如它的增长率不断递减(因为它的导数$y' = frac{1}{sqrt{x}}$,$y'$随$x$减小而减小)。

      所以对于两个决策点$i, j$,若满足$i < j$,如果它们在转移到$p_{k}$的时候$i$没有$j$优,那么$i$不会比$j$优了。

      同样的,如果$i$还是比$j$优,那么在$k$之前还是这样的。  

      因此决策点是单调的。

      所以我们可以用整体二分的写法。

      每次考虑$f[mid]$的函数值,找到它的最优决策点$pos$,那么可以确定左区间的决策点的范围,对于右区间同理。

    Code

     1 /**
     2  * bzoj
     3  * Problem#2216
     4  * Accepted
     5  * Time: 4516ms
     6  * Memory: 13032k
     7  */
     8 #include <bits/stdc++.h>
     9 using namespace std;
    10 typedef bool boolean;
    11 
    12 int n;
    13 int *csqr;
    14 int *ar;
    15 int *f, *g; 
    16 
    17 inline void init() {
    18     scanf("%d", &n);
    19     csqr = new int[(n + 1)];
    20     ar = new int[(n + 1)];
    21     f = new int[(n + 1)];
    22     g = new int[(n + 1)];
    23     for (int i = 1; i <= n; i++)
    24         scanf("%d", ar + i);
    25 }
    26 
    27 double *sqs;
    28 void prepare() {
    29     sqs = new double[(n + 1)];
    30     sqs[0] = 0;
    31     for (int i = 1; i <= n; i++)
    32         sqs[i] = sqrt(i);
    33 }
    34 
    35 void dividing(int* f, int l, int r, int ql, int qr) {
    36     if (l > r)    return;
    37     int mid = (l + r) >> 1, pos;
    38     double mx = 0.0, cmp;
    39     for (int i = ql; i <= qr && i <= mid; i++)
    40         if ((cmp = ar[i] + sqs[mid - i]) > mx)
    41             mx = cmp, pos = i;
    42     f[mid] = ceil(mx - ar[mid]);
    43     dividing(f, l, mid - 1, ql, pos);
    44     dividing(f, mid + 1, r, pos, qr);
    45 }
    46 
    47 inline void solve() {
    48     dividing(f, 1, n, 1, n);
    49     reverse(ar + 1, ar + n + 1);
    50     dividing(g, 1, n, 1, n);
    51     for (int i = 1; i <= n; i++)
    52         printf("%d
    ", max(f[i], g[n - i + 1])); 
    53 }
    54 
    55 int main() {
    56     init();
    57     prepare();
    58     solve();
    59     return 0;
    60 }
  • 相关阅读:
    HDU4474 Yet Another Multiple Problem BFS搜索
    HDU4473 Exam 数学分析
    2013ACM多校联合(4)
    POJ1273 网络流...
    HDU4472 Count 递推
    POJ1149 PIGS 网络流
    UVA10881 Piotr's Ants 想法题
    javascript js string.Format()收集
    修改 设置 vs.net 网站 调试 设为 起始页
    【转】HTML5杂谈 概念与现行游戏 割绳子 宝石迷阵
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8529892.html
Copyright © 2011-2022 走看看