题目描述
ls最近开了一家图书馆,大家听说是ls开的,纷纷过来借书,自然就会出现供不应求的情况, 并且借书的过程类 似一个队列,每次有人来借书就将它加至队尾,每次有人来还书就把书借给队头的若干个人,定义每个人的等待时 间为拿到书的时刻减去加至队列的时刻,如果一个人根本就拿不到书,则等待时间为inf,现在给出所有时刻借书 还书的情况,和若干个询问,每次询问当图书馆初始有x本书时所有人的等待时间之和是多少(如果存在一个人根 本拿不到书,则输出INFINITY) 1<=n,q<=100000
Sol
[一费2/1 把 书 给 我!]
我们先考虑开始书的数量为0的时候,显然我们可以O(N)计算出每个点需要等待的人数,而总的等待时间就是每个点等待的人数求一下和233
考虑修改开始的书的数量到K的过程,其实就是把后面每个点的等待人数减去K,再把大于0的部分求一下和
那么现在我们就有一个非常显然的思路,二分
我们先根据每个点有多少个人在等待排一下序,排序完之后 我们每次就可以用一个log的效率去查找第一个被减去K不小于0的人的位置,然后求一个后缀和就可以了
至于无解的判断就是在K=0的时候,最后一个时间的等待的人数大于开始给的人数,就无解啦233
代码细节还是挺多的…建议考虑清楚再写…[多写了个等号挂了1个小时….]
Code
-
#include <bits/stdc++.h>
-
using namespace std;
-
int N,Q,T[100005],K[100005],Now,NNow;
-
long long Suffix[100005],Suffix1[100005];
-
struct Node
-
{
-
int c;
-
int T;
-
}node[100005];
-
int temp(Node x,Node y){return x.c<y.c;}
-
char c[100005];
-
char qwq[10005];
-
int main()
-
{
-
freopen("expect.in","r",stdin);
-
freopen("expect.out","w",stdout);
-
cin>>N>>Q;
-
for (int i=1;i<=N;i++)
-
scanf("%s%d%d",&qwq,&T[i],&K[i]),c[i]=qwq[0];
-
for (int i=1;i<=N;i++)
-
{
-
if (c[i]=='+') Now+=K[i];
-
if (c[i]=='-') Now-=K[i];
-
if (Now<0)
-
node[i].c=-Now;
-
if (i!=N)
-
node[i].T=T[i+1]-T[i];
-
}
-
int rr=node[N].c;
-
sort(node+1,node+N+1,temp);
-
for (int i=N;i>=0;i--)
-
{
-
Suffix[i]=Suffix[i+1]+node[i].T;
-
Suffix1[i]=Suffix1[i+1]+1ll*node[i].T*node[i].c*1ll;
-
}
-
-
for (int i=1;i<=Q;i++)
-
{
-
scanf("%d",&NNow);
-
int l=0,r=N+1,anss=0;
-
while (l<=r)
-
{
-
int mid=(l+r)>>1;
-
if (node[mid].c<=NNow)
-
l=mid+1;
-
else r=mid-1,anss=mid;
-
}
-
if (NNow<rr)
-
{
-
printf("INFINITY\n");
-
continue;
-
}
-
if (anss==0)
-
{
-
printf("0\n");
-
continue;
-
}
-
long long ans=(Suffix1[anss])-1ll*NNow*(Suffix[anss]);
-
printf("%lld\n",ans);
-
}
-
return 0;
-
}