zoukankan      html  css  js  c++  java
  • BZOJ2216 [POI2011] Lightning Conductor

    https://www.luogu.com.cn/problem/P3515

    即计算最大的aj-ai+sqrt(|i-j|)。先考虑i>j的情况,此时可以验证有决策单调性:当决策点x,y和待计算点i,j满足x<y<i<j时,证明:若ax-ai+sqrt(|i-x|)<ay-ai+sqrt(|i-y|),则必有ax-aj+sqrt(|j-x|)<ay-aj+sqrt(|j-y|)。证明方法把前式的i移到一边然后分子有理化发现单调性即可。i<j时把a反过来同理。

    决策单调性的一般方法是:队列维护决策点及其控制区间(这个控制区间是i~n的,是在仅考虑1~i-1的决策点时的情况,而不一定是最终的),然后用队头(此时它控制i)更新dp(i),并加入决策点i。加入时,从队尾弹出“用i更新某区间左端点,比用原控制该区间的点来更新该区间左端点更好”的区间(即把他们归为i的控制区间),然后在弹完后的队尾的那个区间找到“恰好归i控制的下标最小的点”,从而把该区间劈成两半。劈完后的后一半与原来弹出的那些区间之并即成为i的控制区间。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 
     5 int n;
     6 #define maxn 500011
     7 int head,tail,a[maxn];
     8 struct quenode{int p,l,r;}que[maxn];
     9 double f[maxn],g[maxn];
    10 double cal(int j,int i) {return a[j]+sqrt(i-j)-a[i];}
    11 void dp(double *f)
    12 {
    13     head=tail=1;
    14     for (int i=1;i<=n;i++)
    15     {
    16         if (head<tail) f[i]=cal(que[head].p,i);
    17         que[head].l++;
    18         if (head<tail && que[head].l>que[head].r) head++;
    19         while (head<tail && cal(que[tail-1].p,que[tail-1].l)<cal(i,que[tail-1].l)) tail--;
    20         if (head==tail) que[tail++]=(quenode){i,i+1,n};
    21         else
    22         {
    23             int L=que[tail-1].l,R=que[tail-1].r+1;
    24             while (L<R)
    25             {
    26                 int mid=(L+R)>>1;
    27                 if (cal(que[tail-1].p,mid)>cal(i,mid)) L=mid+1;
    28                 else R=mid;
    29             }
    30             if (L<=n)
    31             {
    32                 que[tail-1].r=L-1;
    33                 que[tail++]=(quenode){i,L,n};
    34             }
    35         }
    36     }
    37 }
    38 
    39 int main()
    40 {
    41     scanf("%d",&n);
    42     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    43     dp(f);
    44     for (int i=1;i+i<=n;i++) {int t=a[i]; a[i]=a[n-i+1]; a[n-i+1]=t;}
    45     dp(g);
    46     for (int i=1;i<=n;i++) printf("%.0lf
    ",max(0.,ceil(max(f[i],g[n-i+1]))));
    47     return 0;
    48 }
    View Code
  • 相关阅读:
    MT【319】分段递推数列
    MT【318】分式不等式双代换
    Centos7环境变量
    VI快捷键
    Centos7 开机自动运行命令
    Centos7 编辑本地DNS解析配置文件
    Centos7修改主机名
    xadmin 自定义过滤器选项
    Centos7网卡配置文件
    Centos7 挂载
  • 原文地址:https://www.cnblogs.com/Blue233333/p/12244919.html
Copyright © 2011-2022 走看看