zoukankan      html  css  js  c++  java
  • APIO2010 特别行动队

    题目不在累述,在RQNOJ或八中上都有。

    朴素方程很好写

    f[i]=max{f[j]+a*sqr(s[i]-s[j])+b*(s[i]-s[j])+c}

    典型的1D/1D方程,有数据范围来看,一定有O(n)算法,于是模式基本就确定下来了,我们要对方程进行变形。

    设对于f[i]决策x优于y且x<y

    则:f[x]+a*(s[i]-s[x])*(s[i]-s[x])+b*(s[i]-s[x])+c>f[y]+a*(s[i]-s[y])*(s[i]-s[y])+b*(s[i]-s[y])+c

    →f[x]+a*s[i]*s[i]-2*a*s[i]*s[x]+a*s[x]*s[x]+b*s[i]-b*s[x]+c>f[y]+a*s[i]*s[i]-2*a*s[i]*s[y]+a*s[y]*s[y]+b*s[i]-b*s[y]+c

    →f[x]-2*a*s[i]*s[x]+a*s[x]*s[x]-b*s[x]>f[y]-2*a*s[i]*s[y]+a*s[y]*s[y]-b*s[y]

    我们令g[i]=f[i]+a*s[i]*s[i]-b*s[i]

    则有g[x]-2*a*s[i]*s[x]>g[y]-2*a*s[i]*s[y]

    →g[x]-g[y]>2*a*s[i]*(s[x]-s[y])

    由于x<y且每一个战斗力均为正,所以s[x]-s[y]<0

    所以(g[x]-g[y])/(s[x]-s[y])<2*a*s[i]

    左边的式子是什么?两点连线的斜率啊!由以上式子,我们可以得到

    对于当前状态i,如果最优状态为p,那么对于j1<p 有 k(j1,p)>=2*a*s[i]

                      对于p<j2 有 k(p,j2)<2*a*s[i]

    满足单调型!!!!!!

    相当与维护一个平面上的点集(s[i],g[i])凸包,每次决策也一定单调,这就让我们用一个队列来维护这个凸包,每个决策最多入队出队各一次,平摊时间复杂度为O(n)

    问题完美解决,特别的队列中有一个点时,它就是当前决策最优点。

    View Code
     1 program APIO(input,output);
     2 var
     3     f,g     :array[0..1000050] of int64;
     4     s     :array[0..1000050] of longint;
     5     q     :array[0..1000050] of longint;
     6     a,b,c    :longint;
     7     n     :longint;
     8 procedure init;
     9 var
    10     i:longint;
    11 begin
    12     readln(n);
    13     readln(a,b,c);
    14     s[0]:=0;
    15     for i:=1 to n do
    16     begin
    17         read(s[i]);
    18         s[i]:=s[i]+s[i-1];
    19     end;
    20 end;{ init }
    21 function K(x,y:longint):double; 
    22 begin
    23     exit(double(g[y]-g[x])/double(s[y]-s[x]));
    24 end; { K }
    25 procedure main;
    26 var
    27     i        :longint;
    28     head,tail:longint;
    29     bestK     :double;
    30 begin
    31     f[0]:=0;
    32     head:=1;
    33     tail:=1;
    34     q[1]:=0;
    35     for i:=1 to n do
    36     begin
    37         bestK:=double(2*a*s[i]);
    38         while (tail-head+1>1)and(K(q[head],q[head+1])>=bestK) do
    39             inc(head);
    40         f[i]:=int64(f[q[head]])+int64(a)*int64(s[i]-s[q[head]])*int64(s[i]-s[q[head]])+int64(b)*int64(s[i]-s[q[head]])+int64(c);
    41         g[i]:=int64(f[i])+int64(a)*int64(s[i])*int64(s[i])-int64(b)*int64(s[i]);
    42         while (tail-head+1>=2)and(K(q[tail],i)>K(q[tail-1],q[tail])) do
    43             dec(tail);
    44         inc(tail);
    45         q[tail]:=i;
    46     end;
    47 end;
    48 procedure print;
    49 begin
    50     writeln(f[n]);
    51 end;
    52 begin
    53     init;
    54     main;
    55     print;
    56 end.
  • 相关阅读:
    Leetcode95. Unique Binary Search Trees II不同的二叉搜索树2
    Leetcode134. Gas Station加油站
    Leetcode152. Maximum Product Subarray乘积的最大子序列
    C#扩展方法
    Lua语言入门
    Docker命令
    SpringBoot-配置文件属性注入-3种方式
    从零开始学Linux系统(五)用户管理和权限管理
    MyCat学习笔记
    kafka-zk-安装测试初体验
  • 原文地址:https://www.cnblogs.com/neverforget/p/2456483.html
Copyright © 2011-2022 走看看