Leading Robots(物理追赶+单调栈)

Leading Robots(物理追赶+单调栈)_第1张图片Leading Robots(物理追赶+单调栈)_第2张图片
这道题我一开始的思路是加速度小到大,然后加速度相同的位置小到大,然后枚举时间复杂度为n方。显然行不通。之后结束后看大佬的题解,才明白了。。。。。。
排序还是我的那个思路。但是在处理谁追赶谁的问题上这两个条件真的难想。
条件:
1.如果排序之后在后面的,那么如果他的位置大于前面的,那么前面的肯定就没有机会做第一。
2.如果有a,b,c。那么c追上b的条件是b追上a的时间必须小于c追上b的时间。如果大于或者等于,那么b还没有追上a的时候已经被c超过了。所以这时b就没有机会第一。
那么条件就是这个了!
在第二个条件中可以用物理公式求解,把他们放在同一起点,然后求解时间:
Leading Robots(物理追赶+单调栈)_第3张图片
求解t1,t2那么就可以令Sa=Sb,Sb=Sc求出来,这样就可以AC了。
这个真的不好想。条件太细了。
AC代码:

#include
using namespace std;
typedef long long ll; 
const ll maxn=5e4+10;
struct Node{
	ll x,a;
}ro[maxn];

bool Judge(Node A,Node B,Node C){
	return (B.x-C.x)*(B.a-A.a)-(C.a-B.a)*(A.x-B.x)<=0;
}
bool cmp(Node A,Node B){
	if(A.a!=B.a)return A.a<B.a;
	else return A.x<B.x;
}
map<pair<ll,ll>,ll> mp;
ll n,top,Stack[maxn];
int main(){
	ll T;
	scanf("%lld",&T);
	while(T--){
		mp.clear();//用来确保不重复的 
		scanf("%lld",&n);
		for(ll i=0;i<n;i++){
			scanf("%lld %lld",&ro[i].x,&ro[i].a);
			pair<ll,ll> p;
			p.first=ro[i].a;
			p.second=ro[i].x;
	        mp[p]++;	
		}
		sort(ro,ro+n,cmp);
		ll top=0;
		for(ll i=0;i<n;i++){
			while((top>0&&ro[i].x>=ro[Stack[top]].x)||(top>1&&Judge(ro[Stack[top-1]],ro[Stack[top]],ro[i]))){//如果top>=0并且ro[i]的位置在顶部元素的后面,那么前面的就不可能得到第一, 
					top--;
			}
			Stack[++top]=i;
		}
		ll ans=top;
		for(ll i=1;i<=top;i++){	
			pair<ll,ll> p;
			p.first=ro[Stack[i]].a;
			p.second=ro[Stack[i]].x;
			if(mp[p]>1)ans--;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

你可能感兴趣的:(stack)