1. 程式人生 > >[BZOJ]4843: [Neerc2016]Expect to Wait 數形結合

[BZOJ]4843: [Neerc2016]Expect to Wait 數形結合

Description

ls最近開了一家圖書館,大家聽說是ls開的,紛紛過來借書,自然就會出現供不應求的情況,並且借書的過程類似一個佇列,每次有人來借書就將它加至隊尾,每次有人來還書就把書借給隊頭的若干個人,定義每個人的等待時間為拿到書的時刻減去加至佇列的時刻,如果一個人根本就拿不到書,則等待時間為inf,現在給出所有時刻借書還書的情況,和若干個詢問,每次詢問當圖書館初始有x本書時所有人的等待時間之和是多少(如果存在一個人根本拿不到書,則輸出INFINITY)。

題解:

好題啊!可以建個座標系,x軸是時間軸,y軸代表當前這個時間點還有多少個人在等待借書,然後x軸上面的面積就是答案,如果初始的書數不同,那麼也就是起點不同。一開始有 x

x 本書,那麼起點就為 ( 0 , x ) (0,-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]); }