题
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
*/