hdu 6107 Typesetting
题
OvO http://acm.hdu.edu.cn/showproblem.php?pid=6107
( 2017 Multi-University Training Contest - Team 6 - 1012)
解
put[i][j]记录第i个数开始用2^j完整行能放下多少个单词,put0[i][j]记录第i个数开始用2^j行被图片占据的行能放下多少个单词
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #define lowbit(x) (x&(-x)) using namespace std; const int M=1e5+44; const int LGM=20; int n,w,w1,w2,pw,dw; int s[M],pre[M]; int put[M][LGM],put0[M][LGM],put1[M][LGM],put2[M][LGM]; int calcu(int wd,int id) { int li=0,ri=(n-id+1)+1,mid; while(li<ri-1) { mid=(li+ri)>>1; if(pre[id+mid-1]-pre[id-1]+(mid-1)>wd) ri=mid; else li=mid; } return li; } void init() { int i,j; w1=dw; w2=w-w1-pw; pre[0]=0; for(i=1;i<=n;i++) pre[i]=pre[i-1]+s[i]; for(i=1;i<=n;i++) { put[i][0]=calcu(w,i); put1[i][0]=calcu(w1,i); put2[i][0]=calcu(w2,i); } for(i=1;i<=n;i++) put0[i][0]=put1[i][0]+put2[i+put1[i][0]][0]; for(i=1;i<=17;i++) for(j=1;j<=n;j++) { put[j][i]=put[j][i-1]+put[j+put[j][i-1]][i-1]; put0[j][i]=put0[j][i-1]+put0[j+put0[j][i-1]][i-1]; } // for(i=0;i<=3;i++) // { // cout<<"i= "<<i<<endl; // for(j=1;j<=n;j++) // cout<<"put: "<<put[j][i]<<' '<<"put1: "<<put1[j][i]<<' '<<"put2: "<<put2[j][i]<<' '<<"put0: "<<put0[j][i]<<endl; // } } int getcount(int id,int h) //get the num, from id ,the hight is h { int tmp,i,j,ret=0; for(i=0;h;i++) if(h&(1<<i)) { h-=(1<<i); tmp=put[id][i]; id+=tmp; ret+=tmp; } // cout<<"ret= "<<ret<<endl; return ret; } int getline(int id,int res) //get the line ,from id ,the rest is res; { int li,ri,mid,ret; li=0; ri=120000; while(li<ri-1) { mid=(li+ri)>>1; if(getcount(id,mid)>=res) ri=mid; else li=mid; } ret=ri; return ret; } int getcount0(int id,int h) { int tmp,i,j,ret=0; for(i=0;h;i++) if(h&(1<<i)) { h-=(1<<i); tmp=put0[id][i]; id+=tmp; ret+=tmp; } return ret; } int getline0(int id,int res) { int li,ri,mid,ret; li=0; ri=120000; while(li<ri-1) { mid=(li+ri)>>1; if(getcount0(id,mid)>=res) ri=mid; else li=mid; } ret=ri; return ret; } void solve(int px,int ph) { int i,j,h,hav=0,now=1; int ans=0,tmp; bool flag=true; if(flag) //part1; { // printf("PART 1:\n"); h=px-1; tmp=getcount(now,h); // cout<<"tmp= "<<tmp<<endl; if(hav+tmp>=n) { tmp=getline(now,n-hav); ans+=tmp+ph; flag=false; } else { hav+=tmp; now+=tmp; ans+=h; } } if(flag) //part2 { // printf("PART 2\n"); h=ph; tmp=getcount0(now,h); // cout<<"tmp= "<<tmp<<endl; if(hav+tmp>=n) { ans+=ph; flag=false; } else { hav+=tmp; now+=tmp; ans+=h; } } if(flag) //part3 { // printf("PART 3\n"); tmp=getline(now,n-hav); ans+=tmp; } printf("%d\n",ans); } int main() { // freopen("数据\\1012.in","r",stdin); // freopen("数据\\fxxl1012.out","w",stdout); int i,j,cas,px,ph,q; scanf("%d",&cas); while(cas--) { scanf("%d%d%d%d",&n,&w,&pw,&dw); for(i=1;i<=n;i++) scanf("%d",&s[i]); init(); scanf("%d",&q); for(i=1;i<=q;i++) { scanf("%d%d",&px,&ph); solve(px,ph); } } return 0; } /* 1 15 36 1 12 15 14 2 36 5 29 28 22 34 10 27 15 33 6 25 5 3 7 8 3 5 15 11 5 9 5 18 14 25 16 15 */