[CF 848B] Rooter's Song 二维弹性碰撞

题意

  在平面直角坐标系中, 有一个以 (0, 0) 为左下角, (w, h) 为右上角的矩形.

  有 n 个人, 它们一开始站在 x 轴或者 y 轴上, 第 i 个人的坐标为 $p_i$ , 准备跳舞.

  对于第 i 个人, 它最开始会在原地站立 t 秒, 然后朝着矩形的对面跳舞, 每 1s 跳 1 个单位长度.

  如果两个人相遇了, 那么它们会相互走另一个人的路线.

  人们会一直走着, 直到它们到达了矩形的某个边界.

  问每个人最后会走到的坐标.

分析

  二维弹性碰撞.

  大致地思路是先回顾一维弹性碰撞, 然后再拓展到二维.

  我们考虑两个人什么时候会碰撞.

  设第一个人的参数为 $p_1, t_1$ , 从 y 轴向右出发.

  设第二个人的参数为 $p_2, t_2$ , 从 x 轴向上出发.

  $p_1 + t_2 = p_2 + t_1$ .

  $p_1 - t_1 = p_2 - t_2$ .

  设 $D_i = p_i - t_i$ ,  $D_i$ 相同的可能会发生碰撞, $D_i$ 不同的一定不会发生碰撞.

  

  一维弹性碰撞规律1: 如果忽略个体之间的差异, 碰撞相当于没有碰撞.

  同样可以用到二维弹性碰撞.

  所以我们可以得知所有最后的坐标.

  一维弹性碰撞规律2: 如果不忽略个体之间的差异, 那么相对顺序不变.

  一维弹性碰撞的相对顺序就是 x 轴.

  观察一下, 发现二维弹性碰撞的相对顺序由二元组 (x, -y) , 即先尽可能让 x 小, 再让 y 大.

  综上, 我们根据 p-t 进行分组, 然后求出组内最终的坐标并进行排序, 再将组内的人按照 (x, -y) 排序, 然后一一对应.

实现

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #include <algorithm>
 6 #include <vector>
 7 using namespace std;
 8 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
 9 inline int rd(void) {
10     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1;
11     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f;
12 }
13
14 const int N = 100005;
15
16 int n, w, h;
17 int g[N], p[N], t[N];
18
19 int Hash[N], tot;
20 inline int Find(int w) { return lower_bound(Hash+1, Hash+tot+1, w) - Hash; }
21
22 struct point {
23     int x, y, id;
24     friend inline bool operator < (point A, point B) { return A.x != B.x ? A.x < B.x : A.y > B.y; }
25 };
26 vector<point> End[N], Lis[N];
27
28 point Go[N];
29
30 int main(void) {
31     #ifndef ONLINE_JUDGE
32         freopen("D.in", "r", stdin);
33     #endif
34
35     n = rd(), w = rd(), h = rd();
36     F(i, 1, n)
37         g[i] = rd(), p[i] = rd(), t[i] = rd(), Hash[++tot] = p[i] - t[i];
38
39     sort(Hash+1, Hash+tot+1);
40     tot = unique(Hash+1, Hash+tot+1)-Hash-1;
41
42     F(i, 1, n) {
43         int Belong = Find(p[i] - t[i]);
44         if (g[i] == 1) {
45             End[Belong].push_back((point){p[i], h, 0});
46             Lis[Belong].push_back((point){p[i], 0, i});
47         }
48         else {
49             End[Belong].push_back((point){w, p[i], 0});
50             Lis[Belong].push_back((point){0, p[i], i});
51         }
52     }
53
54     F(i, 1, tot) {
55         sort(End[i].begin(), End[i].end());
56         sort(Lis[i].begin(), Lis[i].end());
57         for (vector<point>::iterator itE = End[i].begin(), itL = Lis[i].begin(); itE != End[i].end(); itE++, itL++)
58             Go[itL -> id] = *itE;
59     }
60
61     F(i, 1, n)
62         printf("%d %d\n", Go[i].x, Go[i].y);
63
64     return 0;
65 }

[CF 848B] Rooter's Song 二维弹性碰撞

时间: 2024-07-30 20:29:54

[CF 848B] Rooter's Song 二维弹性碰撞的相关文章

二维非对心弹性碰撞的算法

该算法适合常见的二维完全弹性碰撞的场合,支持对心碰撞(正碰)和非对心碰撞(斜碰),不考虑碰撞过程中的机械能损耗,不考虑物体表面摩擦以及恢复系数. /* * this是自身对象,sp是碰撞的对象 * this.m 质量 * this.r 半径 * this.vx 水平速度 * this.vy 竖直速度 * 为了便于理解,代码未经优化!*/ collide(sp) { if (this.isCollideWith(sp)) { // 利用弹性碰撞公式计算水平.竖直方向上的速度分量 let vx =

cf#590 D 二维树状数组

题意 给一个10^5之内的字符串(小写字母)时限2s 输入n,有n个操作  (n<10^5) 当操作是1的时候,输入位置x和改变的字母 当操作是2的时候,输入区间l和r,有多少不同的字母 思路 二维树状数组 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<map> 6 #define lowbit(x) x&am

codeforces 848B Rooter&#39;s Song 思维题

http://codeforces.com/problemset/problem/848/B 给定一个二维坐标系,点从横轴或纵轴垂直于发射的坐标轴射入(0,0)-(w,h)的矩形空间.给出点发射的坐标轴,位置,延迟时间,发生碰撞则交换方向.求最后每个点的射出位置. 首先我们观察能得出两个结论,1. 类似蚂蚁爬树枝的问题,相遇只会交换方向,所以最后的射出点集只会因为碰撞而改变动点与射出点的对应关系,而不会增加减少射出点集.2.我们根据其射入位置和延迟时间可以计算出一个值v=pos-time,只有这

在云平台上基于Go语言+Google图表API提供二维码生成应用

二维码能够说已经深深的融入了我们的生活其中.到处可见它的身影:但通常我们都是去扫二维码, 曾经我们分享给朋友一个网址直接把Url发过去,如今我们能够把自己的信息生成二维码再分享给他人. 这里就分享一下基于Go语言+Google图表API提供二维码生成功能的小应用,并演示怎样把它公布到云平台上, 让每一个人都能够通过网络訪问使用它. Google图表API Google在http://chart.apis.google.com 上提供了一个将表单数据自己主动转换为图表的服务. 只是,该服务非常难交

用python将jenkins构建的apk下载地载生成二维码提供下载

现在移动端的开发中很多团队都用到了jenkins+gradle对android代码打包成apk,然而apk怎么到我们的手机上呢,那就会想到用二维码扫描做这样一个简单的事情: 1.要知道jenkins项目的下载地址 2.要知道jenkins的工具空间及包的存放位置 3.要利用python生成二维码图片 4.要让将图片放入http中可以直接访问. 我只上一下简单的代码,其它的可以根据实际情况改,比如怎么通过文件名获取最新的apk,也可以从urllib从页面获取最新的apk等等 配置文件: [conf

Codeforces 707 E. Garlands (二维树状数组)

题目链接:http://codeforces.com/problemset/problem/707/E 给你nxm的网格,有k条链,每条链上有len个节点,每个节点有一个值. 有q个操作,操作ask问你一个子矩阵的和是多少,操作switch将第i条链上的值0变原来的数or原来的数变0. 比较明显的二维数组数组暴力,注意的是ask操作不会超过2000,所以在switch操作的时候不能进行update操作,否则会超时.所以你在ask操作的时候update就会省时. 复杂度大概是2000*2000*l

(二维数组 亿进制 或 滚动数组) Hat&#39;s Fibonacci hdu1250

Hat's Fibonacci Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 12284    Accepted Submission(s): 4124 Problem Description A Fibonacci sequence is calculated by adding the previous two members t

二维码扫码积分系统定制开发

微信积分系统 二维码扫码积分系统定制开发找丽姐[158.1816.6626/电微]二维码营销模式系统定制开发 微信扫二维码营销系统开发 扫码领积分系统开发 一.如何实现扫二维码领红包功能? 1.使用扫描二维码领取红包对活动进行设置,包括红包数量.红包金额.促销地区.中奖概率等. 2.将生成的二维码赋到商品上面并赋涂层,一方面可以起到保证二维码的一次性,另一方面也可以引起消费者的好奇心. 3.通过手机微信打开扫一扫,扫码商品二维码关注公众号并领取红包,如果参与分享还可以获得抽奖的机会. 二.微信扫

微信生成二维码 只需一个网址即刻 还有jquery生成二维码

<div class="orderDetails-info"> <img src="http://qr.topscan.com/api.php?text=http://123.net/index.php?s=/Home/Index/yanzheng/mai/{$dange.id}" style="width: 5rem; margin-bottom: 1rem;" > </div> http://qr.tops