CF1902D. Robot Queries-二分、思维

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;
}
posted @ 2024-05-09 00:51  yoshinow2001  阅读(9)  评论(0编辑  收藏  举报