本题看上去有点吓人,其实没那么难。
容易发现,只会有某时相邻的两个粒子才会碰撞。考虑使用优先队列作为粒子碰撞的“事件队列”,并同时使用双向链表维护每个粒子与哪两个粒子是相邻的。
大体思路就是这样,但还有一个问题:如何计算两个粒子第几次观察后会碰撞?
对于每个粒子(以哞微子为例),先向右运动 $1$ 秒,再向左运动 $2$ 秒,再向右运动 $3$ 秒,再向左运动 $4$ 秒……拿出草稿纸画一下,其实刚才运动的本质是,Bessie 第 $1$ 次观察时位于 $p+s$,第 $2$ 次观察时位于 $p-s$,然后是 $p+2s$,然后 $p-2s$……
可以得到结论:第 $2k-1$ 次观察,位于 $p+ks$;第 $2k$ 次观察,位于 $p-ks$。反哞微子反之。给定两个粒子之间的距离,就可以解出 $k$。如果左边的是哞微子,答案就是 $2k-1$;如果左边的是反微子,答案就是 $2k$。
// Title: Quantum Moochanics
// Source: USACO24FEB Gold
// Author: Jerrywang
#include <bits/stdc++.h>
#define ll long long
#define rep(i, s, t) for(int i=s; i<=t; ++i)
#define debug(x) cerr<<#x<<":"<<x<<endl;
const int N=200010;
using namespace std;
int n, pre[N], nxt[N]; ll p[N], s[N], res[N];
void del(int i)
{
nxt[pre[i]]=nxt[i], pre[nxt[i]]=pre[i];
}
ll calc(int i, int j)
{
return (p[j]-p[i]+s[i]+s[j]-1)/(s[i]+s[j])*2-(i&1);
}
struct crash
{
int i, j; ll tim;
bool operator <(crash a) const {return tim>a.tim;}
};
priority_queue<crash> q;
void solve()
{
scanf("%d", &n);
rep(i, 1, n) scanf("%lld", p+i), pre[i]=i-1, nxt[i]=i+1, res[i]=0;
nxt[n]=0;
rep(i, 1, n) scanf("%lld", s+i);
rep(i, 1, n-1) q.push({i, i+1, calc(i, i+1)});
while(q.size())
{
auto [i,j,tim]=q.top(); q.pop();
if(res[i] || res[j]) continue;
res[i]=res[j]=tim;
int ii=pre[i], jj=nxt[j];
if(ii && jj) q.push({ii, jj, calc(ii, jj)});
del(i), del(j);
}
rep(i, 1, n) printf("%lld%c", res[i], " \n"[i==n]);
}
int main()
{
#ifdef Jerrywang
freopen("E:/OI/in.txt", "r", stdin);
#endif
int T; scanf("%d", &T);
while(T--) solve();
return 0;
}