[BZOJ]4843: [Neerc2016]Expect to Wait 數形結合
阿新 • • 發佈:2018-12-24
Description
ls最近開了一家圖書館,大家聽說是ls開的,紛紛過來借書,自然就會出現供不應求的情況,並且借書的過程類似一個佇列,每次有人來借書就將它加至隊尾,每次有人來還書就把書借給隊頭的若干個人,定義每個人的等待時間為拿到書的時刻減去加至佇列的時刻,如果一個人根本就拿不到書,則等待時間為inf,現在給出所有時刻借書還書的情況,和若干個詢問,每次詢問當圖書館初始有x本書時所有人的等待時間之和是多少(如果存在一個人根本拿不到書,則輸出INFINITY)。
題解:
好題啊!可以建個座標系,x軸是時間軸,y軸代表當前這個時間點還有多少個人在等待借書,然後x軸上面的面積就是答案,如果初始的書數不同,那麼也就是起點不同。一開始有
本書,那麼起點就為
。可能有點抽象,上個樣例的圖(開始有1本書):
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=100010;
const int inf=2147483647;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n,q;LL ans[Maxn],Ans=0,tot=0;
struct Line{int h,l,r;}L[Maxn];
bool cmpL(Line a,Line b){return a.h>b.h;}
struct Query{int id,x;}Q[Maxn];
bool cmpQ(Query a,Query b){return a.x>b.x;}
int main()
{
n=read(),q=read();
int now=0,tn;
for(int i=1;i<=n;i++)
{
char op[3];int t,k;
scanf("%s",op);
t=read(),k=read();
if(op[0]=='-')now+=k;
else now-=k;
L[i].h=now;L[i].l=t;L[i-1].r=t;
}L[n].r=inf;tn=now;
for(int i=1;i<=q;i++)Q[i].x=read(),Q[i].id=i;
sort(L+1,L+1+n,cmpL);sort(Q+1,Q+1+q,cmpQ);
now=0;
for(int i=1;i<=q;i++)
{
if(i!=1)Ans+=((LL)Q[i-1].x-Q[i].x)*tot;
while(now<n&&L[now+1].h>Q[i].x)
{
now++;
Ans+=((LL)L[now].h-Q[i].x)*((LL)L[now].r-L[now].l);
tot+=((LL)L[now].r-L[now].l);
}
ans[Q[i].id]=Ans;
}
for(int i=1;i<=q;i++)if(Q[i].x<tn)ans[Q[i].id]=-1;
for(int i=1;i<=q;i++)
if(ans[i]==-1)puts("INFINITY");
else printf("%lld\n",ans[i]);
}