codeforces 1311F Moving Points 两种解法

Posted ertuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 1311F Moving Points 两种解法相关的知识,希望对你有一定的参考价值。

题目描述:n个点有速度,有位置,问所有的点对最小距离之和为多少

解法1:离散化 + 树状数组

基本上做出来的都是用的这个方法,不多介绍,看代码吧

#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
const int INF=2000000010;
typedef long long ll;

int n;
struct nb {
    int id, x, v;
} a[maxn];
ll num[maxn], sum[maxn];
bool cmp1(nb a, nb b) {
    return a.x<b.x;
}
bool cmp2(nb a, nb b) {
    if(a.v==b.v) return a.x<b.x;
    else return a.v<b.v;
}

void add(int x, ll res) {
    for(int i=x; i<=n; i+=(i&-i)) num[i]++, sum[i]+=res;
}

ll get_sum(int x) {
    ll ans=0;
    for(int i=x; i>0; i-=(i&-i)) ans+=sum[i];
    return ans;
}

ll get_num(int x) {
    ll ans=0;
    for(int i=x; i>0; i-=(i&-i)) ans+=num[i];
    return ans;
}

int main() {
    scanf("%d", &n);
    for(int i=1; i<=n; i++) scanf("%d", &a[i].x);
    for(int i=1; i<=n; i++) scanf("%d", &a[i].v);
    sort(a+1, a+1+n, cmp1);
    for(int i=1; i<=n; i++) a[i].id=i;
    sort(a+1, a+1+n, cmp2);
    ll ans=0;
    for(int i=1; i<=n; i++) {
        ans+=get_num(a[i].id)*(ll)a[i].x-get_sum(a[i].id);
        add(a[i].id, a[i].x);
    }
    printf("%lld
", ans);
    return 0;
}

解法2:

这个解法就很神奇了,AC之后看了一下CF上别人的解法,嗯?怎么这么简洁

略加思索,懂了,妙呀!

先看一下别人的代码,十分简洁

#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()
{
    cin>>n;
    for( int i=0;i<n;i++)
    {
        cin>>x[i];a[i].second=x[i];
 
    }
    for(int i=0;i<n;i++)cin>>a[i].first;
    sort(a,a+n);
    sort(x,x+n);
    for( int i=0;i<n;i++) {
        ll temp = (i+lower_bound(x,x+n,a[i].second)-x-n+1)*(ll)a[i].second;
        cout<<temp<<endl;
        ans+=(i+lower_bound(x,x+n,a[i].second)-x-n+1)*(ll)a[i].second;
    }
    cout<<ans;
}

因为对于每一个点的坐标,能够用到它的只有两种情况

设这个点坐标为Xn

(1) 坐标在他前面速度比他小的某个点坐标为x0 他们之间的最小距离就是 Xn- X0 了 ans += (Xn - X0)

(2)坐标在他后面速度比他大的某个点坐标为X1 他们之间的最小距离就是X1 - Xn 了 ans +=  (X1 - Xn)

剩下的情况,最小距离都是0,因为总会追上或者被追上,所以不会对ans产生贡献

那么很显然如果情况(1)的点个数为Y,情况(2)的点个数为X

那么坐标Xn对答案产生的贡献就是(Y-X)*Xn

对于代码中的操作当循环到i的时候

lower_bound(x,x+n,a[i].second)-x就是求它的坐标离散化后是第几个,我们设为p

我们设情况(2)的点有X个,那么在他后面但是速度比她小的点有n-1-p-X个

速度比她小点有i个 

情况(1)的点就有Y = i - (n-1-p-X)个

Y - X = i - p - n +1 

X被神奇的消掉了,结束。

 

以上是关于codeforces 1311F Moving Points 两种解法的主要内容,如果未能解决你的问题,请参考以下文章

[CodeForces] Moving Points

@codeforces - 1209H@ Moving Walkways

C.Chips Moving(codeforce1213/A)

Codeforces Round #624 F. Moving Points 离散化 + 树状数组

Hdoj 1050.Moving Tables 题解

HDU 1050 Moving Tables(贪心)