• 倍增优化DP


    对于只考虑首位状态的DP,考虑用倍增优化

    P1081 开车旅行

    https://www.luogu.org/problemnew/show/P1081

     1 const int N=100005;
     2 struct node{int x,y;};
     3 il bool operator <(node a,node b){return a.y<b.y;}
     4 typedef set<node> st;
     5 typedef st::iterator itr;
     6 st s;itr it,lt,rt;
     7 int ii,ga[N],gb[N],t,f[18][N][2],g[10],m,h[N],n,ans;
     8 ll ansA,ansB,a[18][N][2],b[18][N][2],A,B;
     9 
    10 il bool cmp(int a,int b)
    11 {
    12       return abs(h[a]-h[ii]) < abs(h[b]-h[ii]) || (abs(h[a]-h[ii]) == abs(h[b]-h[ii]) && h[a]<h[b]);
    13 }
    14 
    15 il void pre()
    16 {
    17           n=rd();
    18       FOR(i,1,n) h[i]=rd();
    19       for(ii=n;ii;--ii)
    20     {
    21           node p=(node){ii,h[ii]};
    22           s.insert(p);
    23           it=s.find(p);
    24           lt=it,rt=it,m=0;
    25           if(lt!=s.begin()) lt--,g[++m]=lt->x;
    26           if(lt!=s.begin()) lt--,g[++m]=lt->x;
    27           if(rt++,rt!=s.end())
    28         {
    29               g[++m]=rt->x;
    30               if(rt++,rt!=s.end()) g[++m]=rt->x;
    31         }    
    32           sort(g+1,g+m+1,cmp);
    33           if(m) gb[ii]=g[1];
    34           if(m>1) ga[ii]=g[2];
    35     }
    36 }
    View Code
     1 il void work()
     2 {
     3     FOR(i,1,n)
     4     {
     5         if(ga[i]) f[0][i][0]=ga[i],a[0][i][0]=abs(h[ga[i]]-h[i]);
     6         if(gb[i]) f[0][i][1]=gb[i],b[0][i][1]=abs(h[gb[i]]-h[i]);
     7     }
     8     t=(int)(log(n*1.0)/log(2.0)+0.001);
     9     FOR(i,1,t) FOR(j,1,n) FOR(k,0,1)
    10     {
    11         int l;
    12         if(i==1) l=k^1; else l=k;
    13         if(f[i-1][j][k]) f[i][j][k]=f[i-1][f[i-1][j][k]][l];
    14         if(f[i][j][k])
    15         {
    16             a[i][j][k]=a[i-1][j][k]+a[i-1][f[i-1][j][k]][l];
    17             b[i][j][k]=b[i-1][j][k]+b[i-1][f[i-1][j][k]][l];
    18         }    
    19     }
    20 }
     1 il void solve(int s,int x0,ll &A,ll &B)
     2 {
     3       A=B=0;int k=0;
     4       For(i,t,0)
     5     if(f[i][s][k]&&a[i][s][k]+b[i][s][k]<=x0)
     6     {
     7         x0-=a[i][s][k]+b[i][s][k];
     8         A+=a[i][s][k],B+=b[i][s][k];
     9         if(i==0) k^=1;
    10         s=f[i][s][k];
    11     }
    12 }
    13 
    14 il void print()
    15 {
    16       int x0=rd();
    17       ansA=1,ansB=0;
    18       FOR(i,1,n)
    19     {
    20           solve(i,x0,A,B);
    21           if(!B) A=1;
    22           if(A*ansB < B*ansA || (A*ansB==B*ansA && h[i]>h[ans])) ansA=A,ansB=B,ans=i;
    23     }
    24       printf("%d
    ",ans);
    25       m=rd();
    26       FOR(i,1,m)
    27     {
    28           int x=rd(),y=rd();
    29           solve(x,y,A,B);
    30           printf("%lld %lld
    ",A,B);
    31     }
    32 }
    33 
    34 int main()
    35 {
    36       pre();
    37       work();
    38       print();
    39       return 0;
    40 }
    View Code
  • 相关阅读:
    CISCO设备的一些硬件知识
    引用 DOS查QQ好友IP(另附入侵方法)
    【转】端口入侵常用工具分析
    修改CentOS默认yum源为国内yum镜像源
    使用Runtime类运行本地可执行文件
    英汉小词典 java随机存取文件流应用 version1.0
    8086/8088汇编过程练习 实现登录界面及其验证
    批处理伪加密
    快速启动中【显示桌面】的还原方法
    批处理字符串偏移指针
  • 原文地址:https://www.cnblogs.com/universeplayer/p/10649187.html
Copyright © 2020-2023  润新知