zoukankan      html  css  js  c++  java
  • 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 imes10^5\ 1 leq Q leq 3 imes10^5\ -3 imes10^5 leq x,y leq 3 imes10^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 << '
    ';
        }
    }
    
  • 相关阅读:
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 344 反转字符串
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
  • 原文地址:https://www.cnblogs.com/hznumqf/p/15457576.html
Copyright © 2011-2022 走看看