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:
");
		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
");
		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
");
		tmp=getline(now,n-hav);
		ans+=tmp;
	}
	printf("%d
",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

*/

  

  

原文地址:https://www.cnblogs.com/FxxL/p/7349971.html