zoukankan      html  css  js  c++  java
  • HDU 6107 Typesetting

    Problem Description
    Yellowstar is writing an article that contains N words and 1 picture, and the i-th word contains ai characters.
    The page width is fixed to W characters. In order to make the article look more beautiful, Yellowstar has made some rules:

    1. The fixed width of the picture is pw. The distance from the left side of the page to the left side of the photo fixed to dw, in other words, the left margin is dw, and the right margin is W - pw - dw.
    2. The photo and words can't overlap, but can exist in same line.
    3. The relative order of words cannot be changed.
    4. Individual words need to be placed in a line.
    5. If two words are placed in a continuous position on the same line, then there is a space between them.
    6. Minimize the number of rows occupied by the article according to the location and height of the image.
      However, Yellowstar has not yet determined the location of the picture and the height of the picture, he would like to try Q different locations and different heights to get the best look. Yellowstar tries too many times, he wants to quickly know the number of rows each time, so he asked for your help. It should be noted that when a row contains characters or pictures, the line was considered to be occupied.

    题目大意:
    有N个单词,每一个单词长度为(a_i),现在存在一页纸,宽度为W,和一张需要放进纸中的照片,照片的宽度为pw,距离纸的左边x,距离右边W-pw-x,有Q组询问,(x,y)表示照片从第x行开始,长度为y,求把单词和照片都放进纸中,需要占用多少行

    解题报告:
    用时:1h,1WA
    比较简单,直接预处理出:
    (f[i][j])表示在没有照片的行中,从第(i)个单词开始,占用(2^j)行可以放下的单词数
    (g[i][j])表示在有照片的行中,从第(i)个单词开始,占用(2^j)行可以放下的单词数
    我们可以先用二分处理出(f[i][0])(g[i][0])
    显然:
    (f[i][j]=f[i][j-1]+f[i+f[i][j-1]][j-1])
    (g[i][j]=g[i][j-1]+g[i+g[i][j-1]][j-1])
    最后再分照片前的部分,照片的部分,和照片后的三个部分处理即可

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    const int N=1e5+5;
    int n,m,W,pw,lw,rw,a[N],sum[N],f[N][20];
    int g[N][20],maxlen;
    int midit(int sta,int lim){
        if(sta>n || !lim)return 0;
        int l=sta,r=n,mid,ret=l-1;
        while(l<=r){
            mid=(l+r)>>1;
            if(sum[mid]-sum[sta-1]+mid-sta<=lim)
                ret=mid,l=mid+1;
            else r=mid-1;
        }
        return ret-sta+1;
    }
    void prework(){
        int x,y;
        for(int i=1;i<=n;i++){
            f[i][0]=midit(i,W);
            x=midit(i,lw);y=midit(i+x,rw);
            g[i][0]=x+y;
        }
        for(int j=1;j<=maxlen;j++){
            for(int i=1;i<=n;i++){
                if(i+f[i][j-1]<=n)
                    f[i][j]=f[i][j-1]+f[i+f[i][j-1]][j-1];
                else f[i][j]=N;
                if(i+g[i][j-1]<=n)
                    g[i][j]=g[i][j-1]+g[i+g[i][j-1]][j-1];
                else g[i][j]=N;
                if(i+f[i][j]-1>n)f[i][j]=N;
                if(i+g[i][j]-1>n)g[i][j]=N;
            }
        }
    }
    int solve(int s,int d){
        int res=n,x=1,ans=0,tot=s-1;
        for(int i=maxlen;i>=0;i--){
            if(tot>=(1<<i) && res>=f[x][i] && x<=n)
                tot-=(1<<i),res-=f[x][i],x+=f[x][i],ans+=(1<<i);
        }
        int pre=ans+d;
        if(!res)return pre;
        tot=d;
        for(int i=maxlen;i>=0;i--){
            if(tot>=(1<<i) && res>=g[x][i] && x<=n)
                tot-=(1<<i),res-=g[x][i],x+=g[x][i],ans+=(1<<i);
        }
        ans=Max(pre,ans);
        if(!res)return ans;
        for(int i=maxlen;i>=0;i--){
            if(res>=f[x][i] && x<=n)
                res-=f[x][i],x+=f[x][i],ans+=(1<<i);
        }
        return ans;
    }
    void work()
    {
        scanf("%d%d%d%d",&n,&W,&pw,&lw);
        maxlen=log(n)/log(2)+1;rw=W-pw-lw;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
        prework();
        int Q,x,y;cin>>Q;
        while(Q--){
            scanf("%d%d",&x,&y);
            printf("%d
    ",solve(x,y));
        }
    }
    
    int main()
    {
        int T;cin>>T;
        while(T--)work();
        return 0;
    }
    
    
  • 相关阅读:
    js变量的作用域问题
    HTML网页公用头部与尾部的一些方法
    拖动对象ondrag
    子div设置float后导致父div无法自动撑开的问题
    js像素运算问题
    js自动轮播图片的两种循环方法(原创)
    display:none显示和隐藏
    Linux shell脚本基础学习详细介绍(完整版)一
    java技术思维导图(转载)
    VIM编辑命令的技巧
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7562294.html
Copyright © 2011-2022 走看看