题意:给定n个点的初始坐标x和速度v(保证n个点的初始坐标互不相同), d(i,j)是第i个和第j个点之间任意某个时刻的最小距离,求出n个点中任意一对点的d(i,j)的总和。

题解:可以理解,两个点中初始坐标较小的点的速度更大时,总有一个时刻后面的点会追上前面的点,d(i,j) =0。

   否则,即后面的点的速度 <= 前面的点的速度时,两点之间的距离只会越来越大,d(i,j) = abs(xi - xj) (初始距离)。

可以用直线来辅助理解:x = xi + v*t,横轴为t,纵轴为x,若两直线交点t值大于等于0,则d(i,j) = 0。否则交点t值为负 或者两直线平行时,d(i,j)=初始距离。

    所以,立即会想到对点按初始坐标排序,遍历每个点,计算出前面点中 速度小于等于 当前点的 所有点与当前点的初始距离总和。n可达2*10^5,需要找O(n log(n))的算法。

  若当前点下标为i,前面所有速度不大于当前点的点下标为j1,j2,...,相当于求(x[i]-x[j1])+(x[i]-x[j2])+(x[i]-x[j3])... = num * x[i] - sum(x[j])。即需要使用一个数据结构来维护前面速度较小点的数量 和 初始距离x的总和。

  最佳选择就是树状数组,按初始坐标递增的顺序依次添加点的信息,一个树状数组记录小于等于当前速度的点的个数,另一个记录这些点的初始距离总和。

  由于速度范围比较大,需要进行离散化处理,即把n个速度离散成n_个下标,树状数组正好对应这个下标。

详细见代码和注释如下:

 #include<cstdio>
#include<utility> //pair
#include<algorithm> //sort
#include<vector>   //lower_bound, unique
using namespace std; const int maxn = 2e5 + ;
pair<int, int>a[maxn]; //存所有点的(初始坐标,速度)
int v[maxn], n; //所有点的速度,点的个数 long long s1[maxn], s2[maxn]; //两个树状数组
void add(int i, int x) {
while (i <= n) {
s1[i]++; //s1存个数,每次增加1
s2[i] += x; //s2存初始坐标x的总和,每次增加x
i += i & (-i);
}
} long long getSum(long long s[], int i) {
long long res();
while (i > ) {
res += s[i];
i -= i & (-i);
}
return res;
} int main() {
scanf("%d", &n);
for (int i = ; i <= n; i++)scanf("%d", &a[i].first);
for (int i = ; i <= n; i++) {
scanf("%d", v + i);
a[i].second = v[i];
}
sort(a + , a + n + );
sort(v + , v + n + );
int *vend = unique(v + , v + n + ); //速度离散化为 v[1]到v[vend-1 - v]
long long ans = 0LL;
for (int i = ; i <= n; i++) { //按x递增顺序向树状数组中添加点的信息,初始两个树状数组都为空
//得到x第i小的点 的v值 在v数组中对应的下标pos
int pos = lower_bound(v + , vend, a[i].second) - v;
//得到速度小于等于a[i].second的点的个数和x总和
long long sum1 = getSum(s1, pos), sum2 = getSum(s2, pos);
ans += sum1 * a[i].first - sum2; //num * x[i] - num个x[j]的和。(对所有的x[j]<x[i])
add(pos, a[i].first);
}
printf("%lld", ans);
return ;
}

详细讲解Codeforces Round #624 (Div. 3) F. Moving Points的更多相关文章

  1. Codeforces Round #624 (Div. 3) F. Moving Points 题解

    第一次写博客 ,请多指教! 翻了翻前面的题解发现都是用树状数组来做,这里更新一个 线段树+离散化的做法: 其实这道题是没有必要用线段树的,树状数组就能够解决.但是个人感觉把线段树用熟了会比树状数组更有 ...

  2. 详细讲解Codeforces Round #624 (Div. 3) E. Construct the Binary Tree(构造二叉树)

    题意:给定节点数n和所有节点的深度总和d,问能否构造出这样的二叉树.能,则输出“YES”,并且输出n-1个节点的父节点(节点1为根节点). 题解:n个节点构成的二叉树中,完全(满)二叉树的深度总和最小 ...

  3. Codeforces Round #624 (Div. 3) F

    题意: 给出n的质点,带着初位置和速度: 如果中途两点可以相遇dis(i,j)=0: 如果不可以相遇,mindis(i,j): 求n个点的两两质点最小dis(i,j)之和 思路: 因为当初位置x和速度 ...

  4. Codeforces Round #624 (Div. 3)(题解)

    Codeforces Round #624 (Div.3) 题目地址:https://codeforces.ml/contest/1311 B题:WeirdSort 题意:给出含有n个元素的数组a,和 ...

  5. Codeforces Round #485 (Div. 2) F. AND Graph

    Codeforces Round #485 (Div. 2) F. AND Graph 题目连接: http://codeforces.com/contest/987/problem/F Descri ...

  6. Codeforces Round #486 (Div. 3) F. Rain and Umbrellas

    Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/co ...

  7. Codeforces Round #501 (Div. 3) F. Bracket Substring

    题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60 ...

  8. Codeforces Round #499 (Div. 1) F. Tree

    Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...

  9. Codeforces Round #624 (Div. 3)(题解)

    A. Add Odd or Subtract Even 思路: 相同直接为0,如果两数相差为偶数就为2,奇数就为1 #include<iostream> #include<algor ...

随机推荐

  1. Python PE8编程规范

    参考博客:https://blog.csdn.net/weixin_39723544/article/details/82144280 1.使用四个空格而不是tab进行缩进 2.默认使用utf-8编码 ...

  2. String字符串性能优化的几种方案

    String字符串是系统里最常用的类型之一,在系统中占据了很大的内存,因此,高效地使用字符串,对系统的性能有较好的提升. 针对字符串的优化,我在工作与学习过程总结了以下三种方案作分享: 一.优化构建的 ...

  3. 优雅地关闭worker进程

    关闭nginx两种方式 nginx -s stop  立即停止nginx进程  nginx -s quit 优雅地关闭worker进程 开始优雅的关闭worker进程后 01设置定时器 worker_ ...

  4. Spring(六)核心容器 - 注册单例 Bean 实例、SingletonBeanRegistry 简介

    前言 上篇文章我们对注册 Bean 的核心类 BeanDefinitionRegistry 进行了讨论,这里的注册 Bean 是指保存 Bean 的相关信息,也就是将 Bean 定义成 BeanDef ...

  5. ubuntu 14.04 如何设置静态ip

    有线网络: 1. 找到文件并作如下修改: sudo vim /etc/network/interfaces 修改如下部分: auto eth0iface eth0 inet staticaddress ...

  6. 从数组中找到topK的元素(序号)

    问题: 在n个数中找出最大的k个数. 多次求min()或求max() 最简单的方法是对大小为k的数组进行n次求min计算(或者对大小为n的数组进行k次求max计算)最后能够找出最大k个数.复杂度是O( ...

  7. HDU_4496_逆向并查集

    http://acm.hdu.edu.cn/showproblem.php?pid=4496 逆向并查集,先读取,然后从后向前join每次保存答案即可. #include<iostream> ...

  8. python练习——第0题

    原GitHub地址:https://github.com/Yixiaohan/show-me-the-code 题目:将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种 ...

  9. Spring Cloud第十四篇 | Api网关Zuul

    ​ 本文是Spring Cloud专栏的第十四篇文章,了解前十三篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring C ...

  10. 文件传输协议-FTP

    一.FTP概述 FTP(File Transfer Protocol 文件传输协议)C/S结构的应用层协议.由服务端和客户端两个部分共同实现文件传输功能 FTP服务器普遍部署于内网中,具有容易部署.方 ...