CF1902D. Robot Queries-二分、思維

yoshinow2001發表於2024-05-09

link:https://codeforces.com/contest/1902/problem/D
題意:二維平面,一開始在 \((0,0)\) ,有一個由 UDLR 組成的長度為 \(n\) 的移動序列 \(s_1,\dots,s_n\)\(q\) 次詢問,每次問:將 \([l,r]\) 翻轉後能否經過 \((x,y)\).
\(1\leq n,q\leq 2\times 10^5\).


區間翻轉的特性在於,最後到達的位置是不會變的。
假設 \(p_i\) 表示實現了 \([1,i]\) 這些操作後到達的位置,對於 \([0,l-1]\)\([r,n]\) 部分的答案可以直接回答:對每個位置維護一個 vector 表示出現的時間,在上面二分即可。

而對於 \([l,r-1]\) 這一部分,如果能到達 \(p(x,y)\),相當於存在某個序列,使得從原點 \(O\to p_{l-1}\) ,再經過 \(r,r-1,\dots,i\) 的操作到達 \(p\),這等價於經過 \(s_i,\dots,s_r\) 這些操作。
假設 \(v(i,j)\) 表示經過 \([i,j]\) 的操作產生的位移,\(v(i,j)=p_j-p_{i-1}\),則這意味著 \(p_{l-1}+v(i,r)=p\),即 \(p_{l-1}+p_r-p_{i-1}=p\),即查詢 \(p_{i-1}=p_{l-1}+p_r-p\),其中 \(l\leq i\leq r\),那麼 \(l-1\leq i-1\leq r-1\).

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define endl '\n'
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int N=2e5+5;
typedef pair<int,int> pii;
int n,q;
string s;
pii p[N];
map<pii,vector<int>> order;
int main(){
    fastio;
    cin>>n>>q>>s;
    order[{0,0}].push_back(0);
    rep(i,1,n){
        p[i].first =p[i-1].first +(s[i-1]=='R')-(s[i-1]=='L');
        p[i].second=p[i-1].second+(s[i-1]=='U')-(s[i-1]=='D');
        order[p[i]].push_back(i);
    }
    auto check=[&](pii p,int l,int r){
        if(l>r||!order.count(p))return false;
        const vector<int> &ve=order[p];
        auto itr=lower_bound(ve.begin(),ve.end(),l);
        return itr!=ve.end()&&*itr<=r;
    };
    while(q--){
        int x,y,l,r;
        cin>>x>>y>>l>>r;
        int tx=p[r].first +p[l-1].first -x;
        int ty=p[r].second+p[l-1].second-y;
        if(check({x,y},0,l-1)||check({x,y},r,n)||check({tx,ty},l-1,r-1))cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

相關文章