P3103 [USACO14FEB] Airplane Boarding G
P3103 [USACO14FEB] Airplane Boarding G
想象一下飞机有N个座位,N个座位相当于数轴上的1至N共N个整点,第1个座位在整点1处,第2个座位在整点2处,……第N个座位在整点N处。
有N个奶牛排好队,要登陆坐飞机,第N头奶牛在数轴的整点0处,第N−1头奶牛在数轴的整点−1处,……第1头奶牛在数轴的整点−N+1处。第i头奶牛的座位号是Si。注意:每头奶牛都有唯一的一个座位,不会出现多头奶牛有相同的座位号。
在每一秒钟,奶牛会向右移动一步到达下一个整点,前提是没有奶牛挡住它。 当第i头奶牛到达它的座位Si时,它需要花费Ti秒去把行李放到头顶的行李架上,然后坐到自己的位置上,在此过程中,由于飞机通道很窄,所以在第i头奶牛坐到自己座位之前,在它左边的所有奶牛都不能动,要等奶牛i放好行李坐好后才能动。
现在的问题是,至少要多少秒之后,所有的奶牛都能做到自己的座位上?
Solution:
妙妙平衡树思维题,感觉可以入选我写过的的十佳题目了。
我们将点
首先我们很难不想到我们应该按照时间的顺序,也就是输入顺序的倒序来写这题,然后我们仔细思考一下就会发现其实答案由两部分组成:
从起点到终点的距离加上放行李的时间
前一半的答案是固定的,所以我们要做的是如何快速的统计一个点总共会被挡多久的路。
那么什么样的点
首先要满足的肯定是
然后就是
也就是说,如果一个点
然后我们发现我们要维护一种数据结构,单点插入,区间删除,查询区间最大值.那就是平衡树了
然后这题就做完了
Code:
#include<bits/stdc++.h> const int N=2e5+5; using namespace std; int rd(){return rand()*17+rand()*rand()+1;} inline int Max(int x,int y){return x>y ? x : y;} struct FHQ_Treap{ int cnt=0; struct Tree{ int ls,rs,x,y,ans,tag,pri; }t[N<<2]; int Node(int x,int y) { t[++cnt]={0,0,x,y,y,0,rd()}; return cnt; } void push(int x,int k){t[x].x-=k;t[x].y+=k,t[x].ans+=k,t[x].tag+=k;} void pushdown(int x) { if(!t[x].tag)return; if(t[x].ls)push(t[x].ls,t[x].tag); if(t[x].rs)push(t[x].rs,t[x].tag); t[x].tag=0; } void pushup(int x) { if(!x)return; t[x].ans=t[x].y; if(t[x].ls)t[x].ans=Max(t[x].ans,t[t[x].ls].ans); if(t[x].rs)t[x].ans=Max(t[x].ans,t[t[x].rs].ans); return ; } void splite_pos(int x,int &a,int &b,int k) { if(!x){a=b=0;return;} pushdown(x); if(k>=t[x].x) {a=x;splite_pos(t[x].rs,t[x].rs,b,k);} if(k<t[x].x){b=x;splite_pos(t[x].ls,a,t[x].ls,k);} pushup(x); } void splite_val(int x,int &a,int &b,int k) { if(!x){a=b=0;return;} pushdown(x); if(k>=t[x].y) {a=x;splite_val(t[x].rs,t[x].rs,b,k);} if(k<t[x].y){b=x;splite_val(t[x].ls,a,t[x].ls,k);} pushup(x); } int merge(int x,int y) { if(!x||!y)return x|y; pushdown(x);pushdown(y); if(t[x].pri<t[y].pri) { t[x].rs=merge(t[x].rs,y); pushup(x);return x; } else { t[y].ls=merge(x,t[y].ls); pushup(y);return y; } } }T; int s[N],t[N]; int n,rt,ans=0; void work() { ios_base::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>n; rt=T.Node(0,0); for(int i=1;i<=n;i++) { cin>>s[i]>>t[i]; } int a,b,c,tmp; for(int i=n;i;i--) { T.splite_pos(rt,a,b,s[i]); tmp=T.t[a].ans+s[i]+t[i]; ans=Max(ans,tmp); T.push(a,1); T.splite_val(b,b,c,tmp-s[i]+1); rt=T.merge(a,T.merge(T.Node(s[i],tmp-s[i]+1),c)); } cout<<ans; } int main() { //freopen("P3103.in","r",stdin);freopen("P3103.out","w",stdout); work(); return 0; }