• 【Foreign】阅读 [线段树][DP]


    阅读

    Time Limit: 10 Sec  Memory Limit: 256 MB

    Description

      

    Input

      

    Output

      

    Sample Input

      0 10 4 10 2
      3 10
      8 5

    Sample Output

      -20

    HINT

      

    Main idea

      从K走向M,路上有n个收益点,表示到了pos位置可以增加val的收益,每次最多可以走D步,走一次损耗A。求最大收益。

    Solution

      这题必然是一道DP,我们层层深入来思考。

      先从20%考虑:首先我们一下子就想到了暴力DP,令f[i]表示到了第i个收益点的最大收益,显然对于每个收益点我们可以O(n)往前枚举每种情况,两个收益点间到达的方法必然是每次都跳D步,最后补上一段,那么步数就是,这样做就是O(n^2)的算法。

      再考虑另外30%:我们发现,我们可以将pos%D同余的放在一个集合,因为这样的话两点之间到达必然是一直跳D步的,那么显然在同一个集合里的点最后一个点对后面的点贡献更优。由于这时候D<=100,我们先预处理,然后新增点的时候枚举D更新即可。

      考虑100%的做法:我们将前面两种方法结合起来,我们发现,由于中间这个步数是一个上取整的东西,不好维护,于是我们可以把它拆成,这个东西具体是+0还是+1我们可以举例子来思考。发现根据余数有关:当pos[j]%D<pos[i]%D的时候+1,否则+0。然后我们就可以用一个线段树来优化这个DP。对于叶子节点 i 维护 pos%D=i 的最值,这里的最值指的是上述式子中仅仅与 j 有关的一项,因为后面的val[i]以及其它项是都要加的,所以可以不管。然后我们再往线段树里面每次加入f[i],这样显然就是区间查询最值、单点修改的一个线段树结构。效率O(nlogn)

      这里还有一个技巧就是:所以我们维护线段树权值的时候可以不用管pos,最后对于答案加减操作即可。

      这样我们就解决了这道题(≧▽≦)/。

    Code

     1 #include<iostream>
     2 #include<string>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<ctime>
     8 #include<cmath>
     9 using namespace std;  
    10 
    11 typedef long long s64;
    12 const int ONE=1000005;
    13 const s64 INF=1e18;
    14 
    15 int K,M,D,A,n;
    16 s64 F,res;
    17 int pos[ONE],val[ONE];
    18 int Mod;
    19 int li[ONE],Num;
    20 
    21 struct power
    22 {
    23         s64 maxx;
    24 }Node[ONE];
    25 
    26 int get()
    27 {    
    28         int res=1,Q=1;char c;
    29         while( (c=getchar())<48 || c>57 )
    30         if(c=='-')Q=-1;
    31         res=c-48;
    32         while( (c=getchar())>=48 && c<=57 )
    33         res=res*10+c-48;
    34         return res*Q;
    35 }
    36 
    37 void Build(int i,int l,int r)
    38 {
    39         Node[i].maxx = -INF;
    40         if(l==r) return;
    41         int mid=(l+r)>>1;
    42         Build(i<<1,l,mid);    Build(i<<1|1,mid+1,r);
    43 }
    44 
    45 void Update(int i,int l,int r,int L,s64 x)
    46 {
    47         if(l==r)
    48         {
    49             Node[i].maxx = max(Node[i].maxx,x);
    50             return;
    51         }
    52         int mid=(l+r)>>1;
    53         if(L<=mid) Update(i<<1,l,mid,L,x);
    54         else Update(i<<1|1,mid+1,r,L,x);
    55         Node[i].maxx = max(Node[i<<1].maxx , Node[i<<1|1].maxx);
    56 }
    57 
    58 void Query(int i,int l,int r,int L,int R)
    59 {
    60         if(L > R) return;
    61         if(L<=l && r<=R)
    62         {
    63             res=max(res,Node[i].maxx);
    64             return;
    65         }
    66         int mid=(l+r)>>1;
    67         if(L<=mid) Query(i<<1,l,mid,L,R);
    68         if(mid+1<=R) Query(i<<1|1,mid+1,r,L,R);
    69 }
    70 
    71 int main()
    72 {
    73         K=get();    M=get();    D=get();    A=get();
    74         
    75         n=get();
    76         for(int i=1;i<=n;i++)
    77             pos[i]=get(),    val[i]=get();
    78         pos[0]=K;    pos[++n]=M;
    79         
    80         for(int i=0;i<=n;i++)  li[++Num]=pos[i] % D; 
    81         sort(li+1,li+Num+1);    Num=unique(li+1,li+Num+1) - li -1;
    82         
    83         Build(1,1,Num);
    84         Mod = lower_bound(li+1,li+Num+1, K%D) - li;
    85         Update(1,1,Num,Mod,0);
    86         for(int i=1;i<=n;i++)
    87         {
    88             F = -INF;
    89             Mod = lower_bound(li+1,li+Num+1, pos[i]%D) - li;
    90             
    91             res=-INF;    Query(1,1,Num,1,Mod-1);    F=max(F, res - A + val[i] );
    92             res=-INF;    Query(1,1,Num,Mod,Num);    F=max(F, res + val[i]);
    93             
    94             Update(1,1,Num, Mod,F);
    95         }
    96         
    97         printf("%I64d",F + (s64)A*(K/D) - (s64)A*(M/D));
    98 }
    View Code
  • 相关阅读:
    WebApi Ajax 跨域请求解决方法(CORS实现)
    JQuery Ajax POST/GET 请求至 ASP.NET WebAPI
    Hybird APP对接后台:Net WebApi
    Chrome
    centos8平台:用fontconfig安装及管理字体(fc-list/fc-match/fc-cache)
    centos8平台:redis6配置启用io多线程(redis6.0.1)
    centos8平台安装redis6.0.1
    centos8平台:举例讲解redis6的ACL功能(redis6.0.1)
    ImageMagick实现图片加水印(ImageMagick6.9.10)
    centos8上安装ImageMagick6.9.10并压缩图片生成webp缩略图
  • 原文地址:https://www.cnblogs.com/BearChild/p/6492666.html
Copyright © 2020-2023  润新知