题意
数轴上有 N N N个点。其中坐标为 x i x_i xi的点有一个速度为 v i v_i vi(沿 x x x轴正向)。问每两个点之间的最小距离之和。
Sol
对于两个点
i
i
i和
j
j
j,只有
x
i
≤
x
j
x_i \le x_j
xi≤xj并且
v
i
≤
v
j
v_i \le v_j
vi≤vj时,此时两点无法相遇,最短距离就是
∣
x
i
−
x
j
∣
| x_i - x_j|
∣xi−xj∣;其他情况都会相遇,最小距离为0。
将距离从小到大排序,然后速度离散化,每次对答案的贡献就是:比当前点速度还小的点的个数乘上当前点的坐标减去前面多余的。
code
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define br putchar('\n')
#define _x fixed << setprecision
#define debug(x) cerr<< #x << '=' << x << '\n'
#define ok() cout << "Yes\n"
#define gg() cout << "No\n"
#define mem(a, b) memset(a, b, sizeof(a));
#define rep(i, a, b) for (int i = a;i <= b; ++i)
#define rrep(i, a, b) for(int i = a; i >= b; --i)
#define ALL(a) (a).begin(), (a).end()
#define IOS ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
using namespace std;
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1}, dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
const int N = 2e5 + 10;
int cnt[N], sum[N], n; // 点数cnt,前缀和sum
struct Node{
int x, v;
bool operator < (const Node &b) const{
return x < b.x;
}
}p[N];
int lowbit(int x) { return x & -x;}
void add(int pos, int val, int c[])
{
while(pos <= n) {
c[pos] += val;
pos += lowbit(pos);
}
}
int ask(int pos, int c[])
{
int res = 0;
while(pos){
res += c[pos];
pos -= lowbit(pos);
}
return res;
}
void solve()
{
cin >> n;
rep(i, 1, n) cin >> p[i].x;
vector<int> all;
rep(i, 1, n){
cin >> p[i].v;
all.push_back(p[i].v);
}
sort(p + 1, p + 1 + n);
sort(ALL(all));
all.erase(unique(ALL(all)), all.end());
int ans = 0;
rep(i, 1, n)
{
int it = lower_bound(ALL(all), p[i].v) - all.begin() + 1;
ans += p[i].x * ask(it, cnt) - ask(it, sum);
add(it, 1, cnt);
add(it, p[i].x, sum);
}
cout << ans << endl;
}
signed main(){
int T = 1; // cin >> T;
while(T --) solve();
return 0;
}