H. High Load Database
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output
Henry profiles a high load database migration script. The script is the list of nn transactions. The ii-th transaction consists of aiai queries. Henry wants to split the script to the minimum possible number of batches, where each batch contains either one transaction or a sequence of consecutive transactions, and the total number of queries in each batch does not exceed tt.
Unfortunately, Henry does not know the exact value of tt for the production database, so he is going to estimate the minimum number of batches for qq possible values of tt: t1,t2,…,tqt1,t2,…,tq. Help Henry to calculate the number of transactions for each of them.
Input
The first line contains a single integer nn — the number of transactions in the migration script (1≤n≤2000001≤n≤200000).
The second line consists of nn integers a1,a2,…,ana1,a2,…,an — the number of queries in each transaction (1≤ai1≤ai; ∑ai≤106∑ai≤106).
The third line contains an integer qq — the number of queries (1≤q≤1000001≤q≤100000).
The fourth line contains qq integers t1,t2,…,tqt1,t2,…,tq (1≤ti≤∑ai1≤ti≤∑ai).
Output
Output qq lines. The ii-th line should contain the minimum possible number of batches, having at most titi queries each. If it is not possible to split the script into the batches for some titi, output "Impossible" instead.
Remember that you may not rearrange transactions, only group consecutive transactions in a batch.
Example
input
Copy
6 4 2 3 1 3 4 8 10 2 5 4 6 7 8 8
output
Copy
2 Impossible 4 5 4 3 3 3
一、地址链接
二、大致题意
给定n个数a1.a2.. ai 。
询问Q次,每次询问给定一个 ti ,你可以做的操作是合并一段或者多段连续的区间(即区间累加),使得剩下来的区间,大小不能超过 ti ,在每个询问回答最少能合并成多少个区间。
三、大致思路
看到好多题解的思路是小数据暴力预处理出来,然后大数据直接二分前缀和求答案。复杂经过分析是调和级数。
惊叹实在是太巧妙了。但是这里贴出来的是一种更加暴力的整体二分做法。
先思考一下,如果在一个值ti下,这些数能够被分割成mid块,那么肯定也可以被分割成mid+1...mid+2..mid+3或者更多块。这是一定的。那么这里显然就存在着可以被二分的性质。
再分析一下,如果现在明确的告诉你要将原本的数列分割成K个区间,那么我肯定可以二分出一个最大值的最小值 minMax,那么结合上面的性质——如果当前我整体二分到的一个值qry是大于等于minMax的,那么这个qry值应该在左区间去被check,反之则应归在右区间。这样整体二分的思路就明确了。
这个复杂度蒟蒻不太会算QAQ。我觉得应该是 (q^1.5) (logn)^2 。
四、丑陋代码
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
inline int Read()
{
int x=0,f=1;char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
const int N=2e5+5;
struct node{int k,id;}qry[N<<1],ql[N<<1],qr[N<<1];
int n,m;
int val[N],ans[N],sum,maxx,cum[N];
int check(int mid)
{
int l=0,cnt=0;
while(l<n)
{
l=upper_bound(cum+l,cum+1+n,cum[l]+mid)-cum-1;
cnt++;
}
return cnt;
}
int bir(int K)
{
int l=maxx,r=sum;
int ret=sum,mid;
while(l<=r)
{
mid=(l+r)>>1;
if(check(mid)<=K)
{
ret=mid;
r=mid-1;
}
else l=mid+1;
}
return ret;
}
void divide(int l,int r,int s,int t)
{
if(s>t) return;
if(l==r)
{
for(int i=s;i<=t;i++)
{
if(qry[i].k<maxx)ans[qry[i].id]=-1;
else ans[qry[i].id]=l;
}
return;
}
int mid=(l+r)>>1,lp=0,rp=0;
int maxMin=bir(mid);
for(int i=s;i<=t;i++)
{
if(qry[i].k>=maxMin)ql[++lp]=qry[i];
else qr[++rp]=qry[i];
}
for(int i=s;i<=s+lp-1;i++) qry[i]=ql[i+1-s];
for(int i=s+lp;i<=t;i++) qry[i]=qr[i+1-s-lp];
divide(l,mid,s,s+lp-1),divide(mid+1,r,s+lp,t);
}
int main()
{
n=Read();
maxx=sum=0;
for(int i=1;i<=n;i++)val[i]=Read(),sum+=val[i],maxx=max(maxx,val[i]),cum[i]=cum[i-1]+val[i];
m=Read();
for(int i=1;i<=m;i++)
{
qry[i].k=Read();
qry[i].id=i;
}
divide(1,n,1,m);
for(int i=1;i<=m;i++)
{
if(ans[i]==-1)printf("Impossible\n");
else
printf("%d\n",ans[i]);
}
}