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;
    }
    
    
  • 相关阅读:
    EF6.0新特性-DbCommandInterceptor实现非SQL端读写分离
    【转】VS2012 中文版转英文版 英文版转中文版 界面语言切换
    【转】Repository 返回 IQueryable?还是 IEnumerable?
    迟来的零碎笔记
    mysql 列转行,合并字段的方法
    MySQL 5.7.9版本sql_mode=only_full_group_by问题
    mysql实现full outer join
    ubuntu下如何查找某个文件的路径
    mysql之group_concat函数详解
    MySQL 表别名(Alias)
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7562294.html
Copyright © 2011-2022 走看看