• BZOJ2448 : 挖油


    $f[i][j]$表示仅考虑$[i,j]$区间的答案,则

    $f[i][j]=min(max(f[i][k-1],f[k+1][j])+a[k]),ileq kleq j$

    维护出$max$的分界点后用一堆线段树维护即可。

    时间复杂度$O(n^2log n)$。

    #include<cstdio>
    const int N=2005,inf=~0U>>1;
    int M,n,i,j,a[N],g,f[N][N];
    inline void up(int&a,int b){if(a>b)a=b;}
    struct ZKW{
    int v[4100];
    inline void ask(int x,int y,int&t){
      if(x>y)return;
      for(x+=M-1,y+=M+1;x^y^1;x>>=1,y>>=1){
        if(~x&1)up(t,v[x^1]);
        if(y&1)up(t,v[y^1]);
      }
    }
    inline void ins(int x,int y){for(x+=M;x;x>>=1)up(v[x],y);}
    inline void build(){for(int i=1;i<=n+M;i++)v[i]=inf;}
    }T1[N],T2[N];
    inline void add(int x,int y){
      if(x>1)T1[y].ins(x-1,f[x][y]+a[x-1]);
      if(y<n)T2[x].ins(y+1,f[x][y]+a[y+1]);
    }
    int main(){
      scanf("%d",&n);
      for(M=1;M<n+2;M<<=1);
      for(i=1;i<=n;i++)scanf("%d",&a[i]),T1[i].build(),T2[i].build();
      for(i=1;i<=n;i++)add(i,i-1);
      for(i=1;i<=n;i++)f[i][i]=a[i],add(i,i);
      for(i=n;i;i--)for(g=i,j=i+1;j<=n;j++){
        while(g<=j&&f[i][g-1]<f[g+1][j])g++;
        f[i][j]=inf;
        T1[j].ask(i,g-1,f[i][j]);
        T2[i].ask(g,j,f[i][j]);
        add(i,j);
      }
      return printf("%d",f[1][n]),0;
    }
    

      

  • 相关阅读:
    hdu 4002 Find the maximum
    hdu 2837 坑题。
    hdu 3123
    zoj Treasure Hunt IV
    hdu 2053 Switch Game 水题一枚,鉴定完毕
    poj 1430 Binary Stirling Numbers
    hdu 3037 Saving Beans
    hdu 3944 dp?
    南阳oj 求N!的二进制表示最低位的1的位置(从右向左数)。
    fzu 2171 防守阵地 II
  • 原文地址:https://www.cnblogs.com/clrs97/p/5475108.html
Copyright © 2020-2023  润新知