MooFest poj1990 (Java)

问题描述

FJ有n头牛,排列成一条直线(不会在同一个点),给出每头牛在直线上的坐标x。另外,每头牛还有一个自己的声调v,如果两头牛(i和j)之间想要沟通的话,它们必须用同个音调max(v[i],v[j]),沟通起来消耗的能量为:max(v[i],v[j]) * 它们之间的距离。问要使所有的牛之间都能沟通(两两之间),总共需要消耗多少能量。

问题分析

首先将牛按照音调由小到大排序,依次遍历每头牛,因为当前牛的音调最大,所以只需要计算它到其他牛的距离之和。依次计算当前牛和每头牛的距离肯定会超时,只需分别计算两边到当前坐标的距离之和就可了。通过树状数组维持两边点的数量以及两边点的坐标就可以快速计算出当前坐标到其他坐标的距离之和。

算法实现

import java.io.*;
import java.util.Arrays;

public class Main {

    StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    PrintWriter out = new PrintWriter(System.out);

    int read() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    public static void main(String[] args) throws IOException {
        new Main().solve();
    }

    int MAXN = 20005;
    int INF = 1000000007;
    long ans = 0;
    int N ;
    long[] arr = new long[MAXN];
    Pair[] pairs = new Pair[MAXN];
    private void solve() throws IOException {
        N = read();
        for (int i = 0; i < N; i++) {
            pairs[i] = new Pair(read(), read());
        }
        Arrays.sort(pairs, 0, N);
        init();
        for (int i = 0; i < N; i++) {
            long lcnt = sum(bit1, pairs[i].x);
            long rcnt = sum(bit1, MAXN) - lcnt;
            long lsum = sum(bit2, pairs[i].x);
            long rsum = sum(bit2, MAXN) - lsum;
            ans += pairs[i].v * (lcnt*pairs[i].x - lsum + rsum - rcnt*pairs[i].x);
            add(bit1,pairs[i].x, 1);
            add(bit2,pairs[i].x, pairs[i].x);
        }
        out.println(ans);
        out.flush();
    }

    int[] bit1 = new int[MAXN+1];
    int[] bit2 = new int[MAXN+1];
    private void init(){
        Arrays.fill(bit1,0);
        Arrays.fill(bit2,0);
    }
    private long sum(int[] bit, int i){
        long res = 0;
        while (i > 0){
            res = res + bit[i];
            i -= i&-i;
        }
        return res;
    }

    private void add(int[] bit, int i, int a){
        while (i<=MAXN){
            bit[i] += a;
            i += i&-i;
        }
    }

    class Pair implements Comparable<Pair>{
        int v,x;

        public Pair(int v, int x) {
            this.v = v;
            this.x = x;
        }

        @Override
        public int compareTo(Pair o) {
            return v - o.v;
        }
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值