Description
有
N
个单词一个图片,第
1.图片宽度是
2.单词和图片均不能重叠
3.单词的先后顺序不能改
4.一个单词不能跨行,要在同一行
5.如果两个单词在同一行的连续位置,那么要用空格隔开
6.最小化单词和图片所占行数
给出
Q
次查询,每次给出图片的开始行
Input
第一行一个整数
T
表示用例组数,每组用例首先输入四个整数
(T≤10,1≤N,W,Q≤105,1≤pw,ai≤W,0≤dw≤W−pw)
Output
对于每次查询,输出这 n 个单词和这张图片至少占的行数
Sample Input
2
2 7 4 3
1 3
3
1 2
2 2
5 2
3 8 2 3
1 1 3
1
1 1
Sample Output
2
3
3
1
Solution
Code
#include<cstdio>
#include<algorithm>
using namespace std;
namespace fastIO
{
#define BUF_SIZE 100000
//fread -> read
bool IOerror=0;
inline char nc()
{
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if(p1==pend)
{
p1=buf;
pend=buf+fread(buf,1,BUF_SIZE,stdin);
if(pend==p1)
{
IOerror=1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch)
{
return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
}
inline void read(int &x)
{
char ch;
while(blank(ch=nc()));
if(IOerror)return;
for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');
}
inline void readc(char &x)
{
char ch;
while(blank(ch=nc()));
if(IOerror)return;
x=ch;
}
inline void reads(char *x)
{
char ch;
while(blank(ch=nc()));
if(IOerror)return;
int n=0;
while(1)
{
x[n++]=ch;
if(blank(ch=nc()))break;
}
x[n]='\0';
}
#undef BUF_SIZE
};
using namespace fastIO;
#define maxn 100005
int f1[maxn][20],f2[maxn][20];
int T,n,w,pw,dw,a[maxn],q,b[maxn][2],m;
void ST()
{
for(int i=1;i<=n;i++)
{
int sum=a[i],j=i+1;
while(j<=n&&sum+a[j]+1<=w)sum+=a[j]+1,j++;
f1[i][0]=j-i;
}
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i<=n;i++)
f1[i][j]=f1[i][j-1]+f1[i+f1[i][j-1]][j-1];
for(int i=1;i<=n;i++)
{
int sum=0,space=0,j=i;
while(j<=n&&sum+a[j]+space<=dw)sum+=a[j]+space,j++,space=1;
sum=0,space=0;
while(j<=n&&sum+a[j]+space<=w-pw-dw)sum+=a[j]+space,j++,space=1;
f2[i][0]=j-i;
}
for(int j=1;(1<<j)<=m;j++)
for(int i=1;i<=n;i++)
f2[i][j]=f2[i][j-1]+f2[i+f2[i][j-1]][j-1];
}
int RMQ1(int s)
{
int ans=0;
while(s<=n)
{
int j=0;
while((1<<(j+1))<=n&&s+f1[s][j+1]<=n)j++;
s+=f1[s][j];
ans+=(1<<j);
}
return ans;
}
int RMQ2(int s,int h)
{
if(h==0)return s;
while(h&&s<=n)
{
int j=0;
while((1<<(j+1))<=h)j++;
s+=f1[s][j];
h-=(1<<j);
}
return s;
}
int RMQ3(int s,int h)
{
if(h==0)return s;
while(h&&s<=n)
{
int j=0;
while((1<<(j+1))<=h)j++;
s+=f2[s][j];
h-=(1<<j);
}
return s;
}
int main()
{
read(T);
//scanf("%d",&T);
while(T--)
{
read(n),read(w),read(pw),read(dw);
//scanf("%d%d%d%d",&n,&w,&pw,&dw);
for(int i=1;i<=n;i++)read(a[i]);//scanf("%d",&a[i]);
read(q);
//scanf("%d",&q);
m=0;
for(int i=1;i<=q;i++)
{
read(b[i][0]),read(b[i][1]);
//scanf("%d%d",&b[i][0],&b[i][1]);
m=max(m,b[i][1]);
}
ST();
for(int i=1;i<=q;i++)
{
int x=b[i][0],h=b[i][1];
int ans=RMQ1(1);
if(ans<=x-1)printf("%d\n",ans+h);
else
{
ans=x+h-1;
int y=RMQ2(1,x-1);
y=RMQ3(y,h);
if(y<=n)ans+=RMQ1(y);
printf("%d\n",ans);
}
}
}
return 0;
}