zoukankan      html  css  js  c++  java
  • [cf559E]Gerald and Path

    将所有线段的端点(即$a_{i}$和$a_{i}pm l_{i}$)离散,并按照$a_{i}$从小到大排序

    定义$f_{i,,j}$表示前$i$条线段在位置$j$之前最多能覆盖的长度(默认覆盖到$j$,允许覆盖到$j$之后,但该部分不计入覆盖的长度),转移对第$i$条线段的方向分类讨论:

    (关于"默认覆盖到$j$",完整的描述即默认$[a_{i},j]$已经被覆盖,即之后覆盖不计算贡献)

    1.若第$i$条线段向右覆盖,即有
    $$
    f_{i,j}=egin{cases}f_{i-1,j}&(jle a_{i}或a_{i}+l_{i}<j)\f_{i-1,a_{i}}+(j-a_{i})&(a_{i}<jle a_{i}+l_{i})end{cases}
    $$
    2.若第$i$​条线段向左覆盖,即有
    $$
    f_{i,j}=egin{cases}f_{i-1,j}&(jle a_{i}-l_{i})\f_{i-1,a_{i}-l_{i}}+(j-(a_{i}-l_{i}))&(a_{i}-l_{i}<jle a_{i})\max_{1le kle i}left(f_{k-1,a_{i}-l_{i}}+min(a_{k}+l_{k},j)-(a_{i}-l_{i}) ight) &(a_{i}<j)end{cases}
    $$
    这里解释一下第3种情况,考虑枚举最终右端点的位置(如果选$k=i$即不存在,注意此时中间应为$a_{k}$),那么注意到在其之后的直线如果向前覆盖到$a_{i}-l_{i}$之前,即已将整个$[a_{i}-l_{i},a_{i}]$全部覆盖,那么显然一定不如向右覆盖,因此即只需要考虑其之前的线段即可

    综上,时间复杂度为$o(n^{3})$,可以通过

    事实上,还可以进行优化,复杂度的瓶颈在于向左覆盖时$a_{i}<j$的部分,显然该部分可以用线段树优化(只需要对$a_{k}+l_{k}$和$j$的大小关系分类讨论即可),时间复杂度即降为$o(n^{2}log n)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 105
     4 map<int,int>mat;
     5 map<int,int>::iterator it;
     6 int n,m,a[N],l[N],pos[N*3],id[N],posl[N],posm[N],posr[N],f[N][N*3];
     7 bool cmp(int x,int y){
     8     return a[x]<a[y];
     9 }
    10 int main(){
    11     scanf("%d",&n);
    12     for(int i=1;i<=n;i++){
    13         scanf("%d%d",&a[i],&l[i]);
    14         mat[a[i]]=mat[a[i]-l[i]]=mat[a[i]+l[i]]=1;
    15     }
    16     for(it=mat.begin();it!=mat.end();it++){
    17         mat[(*it).first]=++m;
    18         pos[m]=(*it).first;
    19     }
    20     for(int i=1;i<=n;i++)id[i]=i;
    21     sort(id+1,id+n+1,cmp);
    22     for(int i=1;i<=n;i++){
    23         int x=id[i];
    24         posl[i]=mat[a[x]-l[x]];
    25         posm[i]=mat[a[x]];
    26         posr[i]=mat[a[x]+l[x]];
    27     }
    28     for(int i=1;i<=n;i++)
    29         for(int j=1;j<=m;j++){
    30             int x=id[i];
    31             f[i][j]=f[i-1][j];
    32             if (a[x]<pos[j])f[i][j]=max(f[i][j],f[i-1][posm[i]]+min(pos[j]-a[x],l[x]));
    33             if ((a[x]-l[x]<pos[j])&&(pos[j]<=a[x]))f[i][j]=max(f[i][j],f[i-1][posl[i]]+(pos[j]-(a[x]-l[x])));
    34             if (a[x]<pos[j]){
    35                 f[i][j]=max(f[i][j],f[i-1][posl[i]]+l[x]);
    36                 for(int k=1;k<i;k++)f[i][j]=max(f[i][j],f[k-1][posl[i]]+min(a[id[k]]+l[id[k]],pos[j])-(a[x]-l[x]));
    37             }
    38         }
    39     printf("%d
    ",f[n][m]);
    40     return 0;
    41 } 
    View Code
  • 相关阅读:
    feign远程调用问题
    java8--stream
    feign业务组件远程请求 /oauth/token
    redis实现自增序列
    MySQL数据库 相关知识点
    netty
    spring的启动流程及bean的生命周期
    MethodHandleVS反射
    并发与并行
    关于注解的思考
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15292428.html
Copyright © 2011-2022 走看看