Loading

XXI Open Cup. Grand Prix of Korea J. Remote Control 相对位置 启发式合并

XXI Open Cup. Grand Prix of Korea J. Remote Control 相对位置 启发式合并

题意

给定长度为\(N\)的包括上下左右的操作序列,在\((0,0)\)点有一障碍物

需要回答\(Q\)个询问,表示从某个起点开始,按照操作序列移动到达的最终位置,若移动到了障碍物,则撤销此次操作

\[1 \leq N \leq 3 \times10^5\\ 1 \leq Q \leq 3\times10^5\\ -3\times10^5 \leq x,y \leq 3\times10^5 \]

分析

最终位置实际上是相对于障碍物的相对位置,因此我们只关注相对位置,不难想到把移动物体变换成移动障碍物,最终障碍物所在的位置就可以确定所有询问的最终位置

离线处理出所有询问,考虑如果障碍物碰到某个询问,显然我们不能让障碍物停下(这样其他询问就会出问题),由于我们只关注相对位置,相当于询问向冲突的方向移动一单位。由于可能某个单位有多个询问,需要对受影响的两个位置合并,因此考虑启发式合并。复杂度\(O(nlogn)\)

代码

实现时可以使用vector,但是需要注意用指针来\(O(1)\) 寻址

#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef vector<int> VI;
inline ll rd(){
    ll x;
    scanf("%lld",&x);
    return x;
}

map<char,int> dx = {{'R',-1},{'L',1}};
map<char,int> dy = {{'U',-1},{'D',1}};

map<pii,VI*> s;

inline void merge(pii a,pii b){
    vector<int>* v1 = s[a];
    vector<int>* v2 = s[b];
    if(v1 -> size() > v2 -> size()) {
        v1 -> insert(v1 -> end(),v2 -> begin(),v2 -> end());
        v2 -> clear();
        s[b] = v1;
    }
    else {
        v2 -> insert(v2 -> end(),v1 -> begin(),v1 -> end());
        v1 -> clear();
    }
    s.erase(a);
}

int main(){
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    int n;
    cin >> n;
    string ss;
    cin >> ss;
    int q;
    cin >> q;
    for(int i = 0; i < q;i++){
        int x,y;
        cin >> x >> y;
        if(!s.count(make_pair(x,y))) s[make_pair(x,y)] = new VI;
        s[make_pair(x,y)] -> push_back(i);
    }
    int x = 0,y = 0;
    for(auto c:ss){
        int x3 = x + dx[c];
        int y3 = y + dy[c];
        int x4 = x + 2 * dx[c];
        int y4 = y + 2 * dy[c];
        if(s.count(make_pair(x3,y3))) {
            if(s.count(make_pair(x4,y4))) merge(make_pair(x3,y3),make_pair(x4,y4));
            else s[make_pair(x4,y4)] = s[make_pair(x3,y3)],s.erase(make_pair(x3,y3));
        }
        x = x3;
        y = y3;
    }
    vector<pii> ans(q);
    for(auto it:s){
        auto b = it.fi;
        int bx = b.fi;
        int by = b.se;
        VI tmp = *it.se;
        for(auto itt:tmp) ans[itt] = make_pair(bx - x,by - y);
    }
    for(auto it:ans){
        cout << it.fi << ' ' << it.se << '\n';
    }
}
posted @ 2021-10-25 11:11  MQFLLY  阅读(103)  评论(0编辑  收藏  举报