码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces 1311F Moving Points 两种解法

时间:2020-05-19 20:12:18      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:bit   别人   一个   class   get   sum   int   second   long   

题目描述: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\n", 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 两种解法

标签:bit   别人   一个   class   get   sum   int   second   long   

原文地址:https://www.cnblogs.com/ertuan/p/12918853.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!