Codeforces 1311 F. Moving Points (树状数组+离散化)

Description:

There are n n n points on a coordinate axis OX. The i − t h i-th ith point is located at the integer point x i xi xi and has a speed v i vi vi. It is guaranteed that no two points occupy the same coordinate. All n points move with the constant speed, the coordinate of the i − t h i-th ith point at the moment t t t (t can be non-integer) is calculated as x i + t ⋅ v i xi+t⋅vi xi+tvi.

Consider two points i i i and j j j. Let d ( i , j ) d(i,j) d(i,j) be the minimum possible distance between these two points over any possible moments of time (even non-integer). It means that if two points i and j coincide at some moment, the value d ( i , j ) d(i,j) d(i,j) will be 0.

Your task is to calculate the value ∑ 1 ≤ i < j ≤ n d ( i , j ) \sum_{1≤i<j≤n}d(i,j) 1i<jnd(i,j) (the sum of minimum distances over all pairs of points).

Input

The first line of the input contains one integer n ( 2 ≤ n ≤ 2 ⋅ 1 0 5 ) n (2≤n≤2⋅10^5) n(2n2105) — the number of points.

The second line of the input contains n n n integers x 1 , x 2 , … , x n ( 1 ≤ x i ≤ 1 0 8 ) x_1,x_2,…,x_n (1≤x_i≤10^8) x1,x2,,xn(1xi108), where xi is the initial coordinate of the i-th point. It is guaranteed that all xi are distinct.

The third line of the input contains n n n integers v 1 , v 2 , … , v n ( − 1 0 8 ≤ v i ≤ 1 0 8 ) v_1,v_2,…,v_n (−10^8≤vi≤10^8) v1,v2,,vn(108vi108), where v i v_i vi is the speed of the i − t h i-th ith point.

Output

Print one integer — the value ∑ 1 ≤ i < j ≤ n d ( i , j ) \sum_{1≤i<j≤n}d(i,j) 1i<jnd(i,j) (the sum of minimum distances over all pairs of points).

Examples

input

3
1 3 2
-100 2 3

output

3

input

5
2 1 4 3 5
2 2 2 3 4

output

19

input

2
2 1
-3 0

output

0

解题思路:

给出 n n n 个点和他们的初始位置 x x x 和移动速度 v v v ,问所有点对在任意时刻全部最小值的和是多少,不是同一时刻而是每个点对的最小值的和,可以是很多时刻。

时间可以是任意实数,对于任意两点,如果 x i < = x j x_i<=x_j xi<=xj ,且 x i < = v j x_i<=v_j xi<=vj ,那么 i , j i,j ij 永远不可能相遇。否则肯定可以相遇,所以只需要计算 x i < = x j x_i<=x_j xi<=xj ,且 x i < = v j x_i<=v_j xi<=vj 的情况即可。这种情况贡献就是距离,树状数组维护一个和就好了。

AC代码:

const int N = 2e5 + 10;
ll c[N][2], b[N], ans, len; //二维数组0维护有几个比他小的,1计算前缀和
int n;

struct node
{
    int x;
    int v;
} a[N];

bool cmp(node a, node b)
{
    return a.x < b.x;
}

void add(int x, int val)
{
    while (x <= n)
        c[x][0]++, c[x][1] += val, x += lowbit(x);
}

ll ask(int x, int k)
{
    ll res = 0;
    while (x)
        res += c[x][k], x -= lowbit(x);
    return res;
}

int main()
{
    sd(n);
    ans = 0, len = 0;
    rep(i, 1, n)
        sd(a[i].x);
    rep(i, 1, n)
    {
        sd(a[i].v);
        b[i] = a[i].v;
    }
    sort(a + 1, a + 1 + n, cmp);
    sort(b + 1, b + 1 + n);
    len = unique(b + 1, b + 1 + n) - b - 1; //不重复元素个数
    rep(i, 1, n)
    {
        int now = lower_bound(b + 1, b + 1 + len, a[i].v) - b; //找到位置比a[i]远并且速度还比a[i]大的,计算贡献
        ans += a[i].x * ask(now, 0) - ask(now, 1);
        //ask(now, 0)询问得到的是位置比x小速度还小的有几个,
        //ask(now, 1)询问得到的是位置比x小速度还小的前缀和,
        add(now, a[i].x);        
    }
    pld(ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值