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;
}