Codeforces Round #624 (Div. 3) F-Moving Points(树状数组+去重离散化)

题目链接

There are n points on a coordinate axis OX. The i-th point is located at the integer point xi and has a speed 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-th point at the moment t (t can be non-integer) is calculated as xi+t⋅vi.Consider two points i and j. Let 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) will be 0.Your task is to calculate the value ∑1≤i<j≤n d(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⋅105) — the number of points.The second line of the input contains n integers x1,x2,…,xn (1≤xi≤108), 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 integers v1,v2,…,vn (−108≤vi≤108), where vi is the speed of the i-th point.

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

做法一

1.题目大意:在OX坐标轴上有n个点,每个点都有一个速度(可以为负数),每时每刻所有点都以自己的速度不断运动,定义d(i,j)为第i和第j个点在坐标轴上的的最短距离(可以是任意时刻)如果可以相遇则d(i,j)=0,求任意两个节点的d之和。显然两个节点要么相遇要么不相遇,相遇的话d为0,不相遇的话d为初始两点的距离(因为随着时间流逝不相遇的话距离会越来越大)

2.我寒假刚刚入门树状数组,之前做的只是单纯的要么求前缀和要么统计个数,这样的结合在一起运用的还是第一次做,在纸上推了半天,不知道这种关系下怎么建树状数组。最终没写出来,因此再这里总结思路,升华提升(大佬们都很熟悉树状数组因此网上的题解都比较晦涩难懂)

3.首先需要明白的是如果当前xi<xj且vi<=vj,那么两点不会相遇,只需要加上两者差值的绝对值,否则就不统计二者的距离。如果使用树状数组的话,我们需要知道要统计的是每个节点前面有多少个速度小于等于它的节点。如第二组样例输入1 2 4后,三者速度相同,那么其贡献是2*4-(1+2),也就是该节点前面有num个小于等于它的节点,就拿num*x-sum(x-1),后者是节点之前的前缀和。而且要保证后面节点坐标大于当前节点坐标,而且速度也要满足后者大于等于前者。故我们要对速度和坐标分别从小到大进行排序

4.对上面分析完之后,接下来就是如何去建立树状数组了。我们对坐标还是对速度建立对应树状数组呢?我自己就是考虑这个的时候不会了。实际上是我们对去重后的速度数组建立树状数组,而且我们要用另外一个二元组保存坐标和速度的对应关系并对坐标从小到大排序,这样保证了两个序列都是从小到大的排列。我们每次先取当前坐标的速度,使用lower_bound查找在去重的速度排第几位(注意从1开始),我们再通过建立的两个树状数组sum和cnt(分别记录前缀和以及每个速度对应的前面速度有几个点),求出对ans的贡献后再更新这个速度(这里是相对的第几大)以后的树状数组,这样就可以计算出结果

5.我参考了这个博客,感谢博主。每次我都会去列一下是否建立的树状数组符合题目,然后在纸上构造出这个图:
在这里插入图片描述
如图的a对应去重后的速度数组v,而t就是sum和cnt数组,因为博主也是新手,说的可能有点乱,但我当前的理解水平只有这些,如有不当之处请指出

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
#define lowbit(x) (x&(-x))
const int maxn=2e5+10;
pair<ll,ll> a[maxn];

ll sum[maxn],cnt[maxn];
int v[maxn],n;

void update(int i,int k){
    while(i<=n){
        cnt[i]++;  //当前以及之后对应节点数增加一
        sum[i]+=k;  //当前以及之后前缀和增加k
        i+=lowbit(i);
    }
}

ll getSum(int i){
    ll ans=0;
    for(;i;i-=lowbit(i))
        ans+=sum[i];
    return ans;
}

ll getCnt(int i){
    ll ans=0;
    for(;i;i-=lowbit(i))
        ans+=cnt[i];
    return ans;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i].first);
    }
    for(int i=1;i<=n;i++){
        scanf("%lld",&v[i]);
        a[i].second=v[i];
    }
    sort(a+1,a+1+n);
    sort(v+1,v+1+n);
    int tot=unique(v+1,v+n+1)-v-1;  //得到一共多少个去重后的速度
    ll ans=0;
    for(int i=1;i<=n;i++){
        int num=lower_bound(v+1,v+1+tot,a[i].second)-v; //减去v得到的才是当前速度是第几大
        ans+=1LL*getCnt(num)*a[i].first-getSum(num);
        update(num,a[i].first);
    }
    printf("%lld",ans);
}

做法二

这是我去逛CF官网提交记录的时候发现的,而且很多大佬也都这样写%%%,我想了一会没想出来为什么这样写,但是大佬的代码总是简单精炼效率高,orz。先放着等回头再研究

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,x[N];
pair<int,int>a[N];
ll ans;

int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>x[i];
        a[i].second=x[i];
    }
    for(int i=1;i<=n;i++)
        cin>>a[i].first;
    sort(a+1,a+n+1);
    sort(x+1,x+n+1);
    for(int i=1;i<=n;i++){
        //cout<<"("<<x[i]<<","<<a[i].first<<"-"<<a[i].second<<")"<<"-----"<<lower_bound(x+1,x+n+1,a[i].second)-x-n-1<<" "<<i+lower_bound(x+1,x+n+1,a[i].second)-x-n-1<<endl;
        ans+=(i+lower_bound(x+1,x+n+1,a[i].second)-x-n-1)*1LL*a[i].second;
    }
    cout<<ans;
}
发布了128 篇原创文章 · 获赞 7 · 访问量 5274

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/104539711