Codeforces 652F 解題報告

題意

有n只螞蟻在長度爲m個格子的環上,環上的格子以逆時針編號,每隻螞蟻每秒往它面向的方向移動一格。若是有兩隻螞蟻相撞則相互調換方向,問t秒後每隻螞蟻的位置。ios

題解

首先經過觀察能夠發現c++

  • 螞蟻相撞產生的軌跡能夠當作兩隻螞蟻穿過對方
  • 因爲相撞後只會互相調換方向,每隻螞蟻的相對編號不會發生變化,即每隻螞蟻的「鄰居」不會發生變化

也就是說:spa

  • 我能夠經過計算每隻螞蟻毫無阻礙產生的軌跡知道t秒後哪些位置上有螞蟻
  • 又因爲每隻螞蟻的相對編號不變,我只要知道某隻螞蟻t秒後的位置就能夠推算出剩下的全部螞蟻的位置

如今的問題就由第一個問題轉換成第二個問題:code

  • t秒後第x個螞蟻的位置是哪
  • t秒後第x個位置的螞蟻編號是多少

對於第二個問題,咱們只要求出t秒後螞蟻按位置編號大小排序的序列就能夠算出答案。假設一開始螞蟻按初始位置編號的大小順序排好,位置0(位置1與位置m的中間)是一個臨界點,考慮兩種狀況來求出t秒後螞蟻的順序:排序

  • t秒內全部螞蟻沒有發生碰撞:當有螞蟻從1通過0走到m時,那麼這隻螞蟻就會變成最後一隻螞蟻,第二隻螞蟻會變成第一隻,以此類推。同理,當有螞蟻從m通過0走到1時,這隻螞蟻就會變成第一隻螞蟻。所以咱們只要計算t秒內螞蟻有多少次從右至左走過0點或從左至右走過0點,求差就能夠獲得螞蟻在t秒後的順序。ci

  • t秒內有螞蟻發生碰撞:若是有螞蟻發生碰撞,由於螞蟻的軌跡能夠當作穿過對方,所以咱們仍是能夠忽略掉碰撞的狀況去計算螞蟻從兩個方向經過0點的次數,就當成上面那種狀況。每從右向左經過0點一次,螞蟻的排列序列就左移一次,向右同理。it

舉個例子,假如一開始螞蟻編號的排列順序爲[1,3,2],在某一秒2從m點經過了0點到1點,序列變成[2,1,3]。假如2與1發生碰撞,2再次反向經過0點,排列順序又變回[1,3,2]。看上去好像要判斷螞蟻2從不一樣方向通過了0點,可是咱們徹底能夠忽略碰撞當作螞蟻2從左邊通過了一次0點和螞蟻1從右邊通過了一次0點,對於複雜的狀況也徹底適應。io

此時咱們已知:class

  • t秒後那些位置上有螞蟻
  • t秒後螞蟻按位置的排序

咱們就能夠直接一一對應上螞蟻的位置了sort

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define per(i, a, b) for(int i=(a-1); i>=(b); i--)
typedef long long ll;
const int maxn = 300005;
const int inf = 0x3f3f3f3f;
struct A {
    ll pos;
    char f;
    bool operator<(const A &x) const {
        return pos < x.pos;
    }
}a[maxn];
int id[maxn], ans[maxn];
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    ll n, m, t;
    cin >> n >> m >> t;
    int offset = 0;
    rep(i, 0, n) {
        id[i] = i;
        cin >> a[i].pos >> a[i].f;
        a[i].pos--;
    }
    //排序獲得螞蟻的初始排列
    sort(id, id + n, [&](int x, int y) { return a[x].pos < a[y].pos; });
    //計算螞蟻t秒後的排列,順便算出t秒後哪些位置出現了螞蟻
    rep(i, 0, n) {
        if (a[i].f == 'L') {
            offset = (offset + (a[i].pos - t - m + 1) / m) % n;
            a[i].pos = ((a[i].pos - t)%m + m) % m;
        }
        else {
            offset = (offset + (a[i].pos + t) / m) % n;
            a[i].pos = (a[i].pos + t) % m;
        }
    }
    offset = (offset + n) % n;
    //對位置排序
    sort(a, a + n);
    //此時初始次序爲i編號爲id[x]的螞蟻在t秒後變成了次序爲(i+offset)%n的螞蟻
    rep(i, 0, n) ans[id[i]] = a[(i + offset)%n].pos + 1;
    rep(i, 0, n) cout << ans[i] << ' ';
    return 0;
}
相關文章
相關標籤/搜索