题目大意
有 n n n 个机器人和 n n n 个天线,分布在直线上,坐标各不相同。如果我们激活某一条天线,那么离它最近的机器人会移动到天线处爆炸,而其他机器人不动。如果两个机器人和天线距离相同,那么左侧的机器人移动。需要构造一个激活顺序,让机器人移动的距离之和尽可能小,输出距离之和与激活顺序。保证输入机器人和天线坐标分别递增
解题思路
显然,从左到右,让机器人和天线一一对应,机器人的移动总距离是最小的。
那么,如何构造顺序让机器人和天线正好可以一一对应呢?首先可以考虑最左侧的天线。如果最左侧的天线,左侧没有机器人,那么激活它之后一定是最左侧的机器人会移动,激活它没有任何问题。如果最左侧的天线对应的机器人在它的左边,那么就把它暂存入栈,然后继续判断下一个。如果遇到一个天线,对应的机器人在它右边,那么结合栈顶元素,构成一种情况:中间两个天线,两侧是它们对应的机器人。那么至少有一个天线,激活后是可以吸引正确的机器人的。循环直至末尾,如果栈中还有剩余元素,那么一定可以从右向左依次输出(因为栈中保存的元素,都是机器人在对应天线的左侧)
参考代码
#include<bits/stdc++.h>
using namespace std;
int a[200010], b[200010];
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i ++){
cin >> a[i];
}
for(int i = 1; i <= n; i ++){
cin >> b[i];
}
long long x = 0;
for(int i = 1; i <= n; i ++)x += abs(a[i] - b[i]);
cout << x << '\n';
stack<int> s;
for(int i = 1; i <= n; i ++){
if(a[i] > b[i]){
while(!s.empty() and b[s.top()] - a[s.top()] <= a[i] - b[s.top()]){
cout << s.top() << ' ';
s.pop();
}
cout << i << ' ';
}
else{
s.push(i);
}
}
while(!s.empty()){
cout << s.top() << ' ';
s.pop();
}
return 0;
}