codeforces 848B Rooter's Song 思维题

Posted Luke_Ye

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 848B Rooter's Song 思维题相关的知识,希望对你有一定的参考价值。

http://codeforces.com/problemset/problem/848/B

给定一个二维坐标系,点从横轴或纵轴垂直于发射的坐标轴射入(0,0)-(w,h)的矩形空间。给出点发射的坐标轴,位置,延迟时间,发生碰撞则交换方向。求最后每个点的射出位置。

首先我们观察能得出两个结论,1. 类似蚂蚁爬树枝的问题,相遇只会交换方向,所以最后的射出点集只会因为碰撞而改变动点与射出点的对应关系,而不会增加减少射出点集。2.我们根据其射入位置和延迟时间可以计算出一个值v=pos-time,只有这个值相等才可能发生碰撞。

这样我们可以把所有点根据值v分成若干个集合,每个集合互不干涉,对于一个集合的射出点集,我们只要处理内部的对应关系即可。

首先画一张图片,代表一个集合的所有点,因为v相等,只要在图中的射线可以相遇一定会碰撞。

 

可见一个点从出发后,将依次交替遭遇另一个轴的点(数量为siz0)和本轴坐标大于等于本身的点(数量为siz1)。最终不再碰撞时的方向我们可以很容易地通过siz0,siz1推出来,而方向与最后一次碰撞的点相同(当与当前方向的平行的坐标轴发射的动点数量用尽时就不再碰撞了)。

这样每个点都可以在O(1)或O(log(n))下求出射出位置。因为需要排序预处理,所以要不要优化到O(1)并不是很重要。

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#define LL long long
using namespace std;
const LL N = 100005;
LL n, w, h;
struct node
{
    LL g, p, t;
};
map<LL, vector<LL> > g[2];
node v[N];
int main()
{
    cin.sync_with_stdio(false);
    while (cin >> n>>w>>h)
    {
        g[0].clear(), g[1].clear();
        
        for (int i = 0; i < n; i++)
        {
            node temp;
            cin >> temp.g >> temp.p >> temp.t;
            temp.g--;
            g[temp.g][temp.p - temp.t].push_back(temp.p);
            v[i] = temp;
        }
        for (map<LL, vector<LL> >::iterator it = g[0].begin(); it != g[0].end(); it++)
            sort(it->second.begin(), it->second.end());
        for (map<LL, vector<LL> >::iterator it = g[1].begin(); it != g[1].end(); it++)
            sort(it->second.begin(), it->second.end());
        for (int i = 0; i < n; i++)
        {
            node e = v[i];
            int dg;
            if (e.g == 0)
            {
                dg = 1;
                LL siz[2];
                siz[e.g]= g[e.g][e.p - e.t].end() - lower_bound(g[e.g][e.p - e.t].begin(), g[e.g][e.p - e.t].end(), e.p);
                siz[dg] = g[dg][e.p - e.t].size();
                LL miz = min(siz[0], siz[1]);
                if (siz[e.g] <= siz[dg])
                    cout << w << \' \' << g[dg][e.p - e.t][miz-1] << endl;
                else
                    cout << g[e.g][e.p - e.t][g[e.g][e.p - e.t].size()-siz[e.g]+miz] << \' \' << h << endl;
            }
            else
            {
                dg = 0;
                LL siz[2];
                siz[e.g] = g[e.g][e.p - e.t].end() - lower_bound(g[e.g][e.p - e.t].begin(), g[e.g][e.p - e.t].end(), e.p);
                siz[dg] = g[dg][e.p - e.t].size();
                LL miz = min(siz[0], siz[1]);
                if (siz[e.g] <= siz[dg])
                    cout << g[dg][e.p - e.t][miz-1]<<\' \'<<h << endl;
                else
                    cout << w<<\' \'<<g[e.g][e.p - e.t][g[e.g][e.p - e.t].size() - siz[e.g] + miz]<<endl;
            }
        }
        
    }
    
    return 0;
}

 

以上是关于codeforces 848B Rooter's Song 思维题的主要内容,如果未能解决你的问题,请参考以下文章

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

排序规律Codeforces Round #254 (Div. 2) - D. Rooter's Song

vuex

[Codeforces]Codeforces Round #490 (Div. 3)

Codeforces Round #725 (Div. 3)Codeforces-1538

Codeforces Round #805 (Div. 3) 题解