详细讲解Codeforces Round #624 (Div. 3) F. Moving Points

题意:给定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的更多相关文章
- Codeforces Round #624 (Div. 3) F. Moving Points 题解
第一次写博客 ,请多指教! 翻了翻前面的题解发现都是用树状数组来做,这里更新一个 线段树+离散化的做法: 其实这道题是没有必要用线段树的,树状数组就能够解决.但是个人感觉把线段树用熟了会比树状数组更有 ...
- 详细讲解Codeforces Round #624 (Div. 3) E. Construct the Binary Tree(构造二叉树)
题意:给定节点数n和所有节点的深度总和d,问能否构造出这样的二叉树.能,则输出“YES”,并且输出n-1个节点的父节点(节点1为根节点). 题解:n个节点构成的二叉树中,完全(满)二叉树的深度总和最小 ...
- Codeforces Round #624 (Div. 3) F
题意: 给出n的质点,带着初位置和速度: 如果中途两点可以相遇dis(i,j)=0: 如果不可以相遇,mindis(i,j): 求n个点的两两质点最小dis(i,j)之和 思路: 因为当初位置x和速度 ...
- Codeforces Round #624 (Div. 3)(题解)
Codeforces Round #624 (Div.3) 题目地址:https://codeforces.ml/contest/1311 B题:WeirdSort 题意:给出含有n个元素的数组a,和 ...
- Codeforces Round #485 (Div. 2) F. AND Graph
Codeforces Round #485 (Div. 2) F. AND Graph 题目连接: http://codeforces.com/contest/987/problem/F Descri ...
- Codeforces Round #486 (Div. 3) F. Rain and Umbrellas
Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/co ...
- Codeforces Round #501 (Div. 3) F. Bracket Substring
题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60 ...
- Codeforces Round #499 (Div. 1) F. Tree
Codeforces Round #499 (Div. 1) F. Tree 题目链接 \(\rm CodeForces\):https://codeforces.com/contest/1010/p ...
- Codeforces Round #624 (Div. 3)(题解)
A. Add Odd or Subtract Even 思路: 相同直接为0,如果两数相差为偶数就为2,奇数就为1 #include<iostream> #include<algor ...
随机推荐
- (转)KL散度的理解
KL散度(KL divergence) 全称:Kullback-Leibler Divergence. 用途:比较两个概率分布的接近程度.在统计应用中,我们经常需要用一个简单的,近似的概率分布 f * ...
- Kubernetes-Service资源详解
service的三种工作模式:(userstats(效率低).iptables.ipvs) service可以自动实现负载均衡.service自动实现了负载均衡,service通过selector标签 ...
- 【转载】计算机程序的思维逻辑 (82) - 理解ThreadLocal
本节,我们来探讨一个特殊的概念,线程本地变量,在Java中的实现是类ThreadLocal,它是什么?有什么用?实现原理是什么?让我们接下来逐步探讨. 基本概念和用法 线程本地变量是说,每个线程都有同 ...
- MySQL学习笔记——基础与进阶篇
目录 一.###MySQL登录和退出 二.###MySQL常用命令 三.###MySQL语法规范 四.###基础查询 五.###条件查询 六.###排序查询 七.###常见函数的学习 八.###分组查 ...
- codeforces 1025B Weakened Common Divisor(质因数分解)
题意: 给你n对数,求一个数,可以让他整除每一对数的其中一个 思路: 枚举第一对数的质因数,然后暴力 代码: #include<iostream> #include<cstdio&g ...
- 关于在osgearth 中 出现 arial.ttf : file not handled 的问题
这是由于配置osg时 freetype 插件没有配置到位. 我个人的解决方法 打开CMAKE,点击advance,不勾选OSG_TEXT_USE_FONTCONFIG. 同时将freetype路径设置 ...
- 【C++】随机数引擎
rand() 基本:使用随机数时,经常见到的是C标准库提供的函数rand(),这个函数会生成一个0到RAND_MAX之间的一个整形数: 分布:为了得到一个给定范围内的随机数,通常会对生成的随机数取余: ...
- 从底层入手,解析字节码增强和Btrace应用
这篇文章聊下字节码和相关的应用. 1.机器码和字节码 机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据. 通常意义上来 ...
- Descriptor - Python 描述符协议
描述符(descriptor) descriptor 是一个实现了 __get__. __set__ 和 __delete__ 特殊方法中的一个或多个的. 与 descriptor 有关的几个名词解释 ...
- delphi制作res文件
第一步:将brcc32.exe拷贝到某个目录,如“res文件”第二步:制作rc文件1.在“res文件”中新建一个文本文件resources.rc:2.文本文件中每一行写一个资源,资源格式为:资源标识名 ...