题目大意:
每个人要办理签证都必须到大使馆中办理三种手续,而且这三种手续办的顺序是固定的。给出办理每种手续的窗口有多少个,办理每个手续花费的时间,有多少人会来办理手续,一级每个人会在什么时间来。要求的是所有人分别在大使馆待的最长时间是多少。
做法:
一种贪心的做法,由于只有三种手续,那么每个人进入办理的时候,
保证选办理同种手续的所有窗口中最早等待的那一个窗口(为什么会有等待?因为该窗口办完了上一个,而下一个没能马上到这一个窗口)。接下来对每个人分开处理,计算出每个人从进入大使馆到办完三种手续离开大使馆需要多少时间,最后去最大的一个就行。
那么关键点就是怎么计算出这个时间。
前面已经提到,只需要去每种窗口最早等待的那一个窗口即可,那么这样的话,我们需要知道
同种类型的窗口的处于等待的时间的最小值,并且修改这个最小值。涉及到这样的操作的话,那当然想到了线段树。我们用三个线段树,分别处理不同类型的窗口的信息。
那有人会想,窗口的个数不是多达10^9个吗?怎么建立这样的线段树?其实这只是个障眼法,总人数最多只能由10^5个,那么最多会用到的窗口最多也就10^5个而已,我们建立树的时候只需要建立窗口数和人数的较小值即可。那这样最终复杂度为O(n*logn)。
代码:
#include <iostream>
#include <cstdio>
#include <climits>
#include <algorithm>
#define N 100010
#define L(x) (x)<<1
#define R(x) (x)<<1|1
using namespace std;
struct node
{
long long ll,rr,mi,pos;
node()
{
ll=rr=pos=0;
mi=INT_MAX;
}
node(long long l,long long r,long long m,long long p)
{
ll=l,rr=r,mi=m,pos=p;
}
}ty[4][N*4];
long long k[4][N],n[4],t[4],peo[N];
long long nn;
void bulid(long long id,long long l,long long r,long long na)
{
ty[na][id]=node(l,r,0,l);
if(l==r) return ;
long long mid=(l+r)/2;
bulid(L(id),l,mid,na);
bulid(R(id),mid+1,r,na);
}
void update(long long id,long long k,long long a,long long na)
{
if(k==ty[na][id].ll && ty[na][id].rr==k){ty[na][id].mi=a;return ;}
long long mid=(ty[na][id].ll+ty[na][id].rr)/2;
if(k>mid) update(R(id),k,a,na);
else update(L(id),k,a,na);
if(ty[na][L(id)].mi<=ty[na][R(id)].mi)
{
ty[na][id].mi=ty[na][L(id)].mi;
ty[na][id].pos=ty[na][L(id)].pos;
}
else
{
ty[na][id].mi=ty[na][R(id)].mi;
ty[na][id].pos=ty[na][R(id)].pos;
}
}
long long query(long long id,long long l,long long r,long long na,long long &index)
{
if(ty[na][id].ll==l&&ty[na][id].rr==r)
{
index=ty[na][id].pos;
return ty[na][id].mi;
}
long long mid=(ty[na][id].ll+ty[na][id].rr)/2;
if(mid>=r) return query(L(id),l,r,na,index);
else if(mid<l) return query(R(id),l,r,na,index);
else
{
long long tmp1,tmp2;
long long t1=query(L(id),l,mid,na,tmp1);
long long t2=query(R(id),mid+1,r,na,tmp2);
if(t1<=t2) {index=tmp1;return t1;}
else {index=tmp2;return t2;}
}
}
int main()
{
for(long long i=1;i<=3;i++)
scanf("%I64d",&n[i]);
for(long long i=1;i<=3;i++)
scanf("%I64d",&t[i]);
scanf("%d",&n[0]);
for(long long i=0;i<n[0];i++)
scanf("%I64d",peo+i),peo[i]--;
for(long long i=1;i<=3;i++)
bulid(1,1,min(n[i],n[0]),i);
long long ans=0;
for(long long i=0;i<n[0];i++)
{
long long cur=peo[i];
for(long long j=1;j<=3;j++)
{
long long index;
long long c_mi=query(1,1,min(n[j],n[0]),j,index);
if(c_mi>=cur) cur=c_mi+t[j];
else cur+=t[j];
update(1,index,cur,j);
}
ans=max(ans,cur-peo[i]);
}
cout<<ans<<endl;
return 0;
}