Codeforces Round #545 (Div. 1) E. Train Car Selection
Vasya likes to travel by train, but doesn't like when the car he travels in is located in the tail of the train.
Vasya gets on the train at the station. The train consists of nn cars indexed from 11 to nn counting from the locomotive (head of the train). Three types of events occur while the train is moving:
- Some number of cars are added to the head of the train;
- Some number of cars are added to the tail of the train;
- Vasya recalculates the values of the convenience of the cars (read more about it below).
At each moment of time we will index the cars from the head of the train, starting from 11. Note that when adding new cars to the head of the train, the indexing of the old ones may shift.
To choose which car to go in, Vasya will use the value AiAi for each car (where ii is a car index), which is calculated as follows:
- At the beginning of the trip Ai=0Ai=0, as well as for the new cars at the time of their addition.
- During the next recalculation Vasya chooses some positive integers bb and ss and adds to all AiAi value b+(i−1)⋅sb+(i−1)⋅s.
Vasya hasn't decided yet where he will get on the train and where will get off the train, so after each event of one of the three types he wants to know the least index of the car, such that its value AiAi is minimal. Since there is a lot of cars, Vasya asked you to write a program that answers his question.
很容易可以发现,每次插入k个数时,其实只有第一个是有用的,而且当插入在队首时,可以直接将队列里面的所有值全部弹出。
所以可以开一个单调递减的栈维护一下,每次只需要判断栈顶的值是否大于前一个的值即可。
但是这样有一个问题,可能会出现一种情况,满足栈顶的值小于前一个,但是已经大于了前面的另一个值。
这种情况很容易处理,只要我们加入值得判断一下,新加入的值超过前一个值的速度是否大于前一个的值超过再前一个的值即可。
这样一来,这个栈就可以满足当一个值超过前一个值的时候,前一个值要么没超过再前一个的值,要么刚好超过,于是就能避免上述提到的情况。
至于位置,B值和S值的维护都很简单,在此不加赘述。
#include<cstdio> #include<cstring> #include<algorithm> #define N 500000 #define ll long long using namespace std; ll n,m,opt,k,b,s,K,B,S,kp[N],bp[N],sp[N],top,data[N],num,mp; ll gets(ll x){ return B-bp[x]+(S-sp[x])*(kp[x]-1); } double getp(ll x,ll y){ return (double)(gets(x)-gets(y))/(kp[y]-kp[x]); } int main(){ scanf("%lld%lld",&n,&m); mp=m; top=1; num=1; data[1]=1; kp[1]=1; K=n; while (m--){ scanf("%lld",&opt); if (opt==1){ scanf("%lld",&k); num++; kp[num]=1; bp[num]=B;sp[num]=S; K+=k; top=1; data[1]=num; printf("1 0\n"); } if (opt==2){ scanf("%lld",&k); num++; kp[num]=K+1; bp[num]=B;sp[num]=S; K+=k; if (gets(data[top])==0){ printf("%lld %lld\n",kp[data[top]],0); continue; } top++; data[top]=num; while (top>2&&getp(data[top-2],data[top-1])<=getp(data[top-1],data[top])){ data[top-1]=data[top]; top--; } printf("%lld %lld\n",kp[data[top]],0); } if (opt==3){ scanf("%lld%lld",&b,&s); B+=b; S+=s; while (top>1&&gets(data[top])>=gets(data[top-1])) top--; printf("%lld %lld\n",kp[data[top]],gets(data[top])); } } return 0; }