[ABC385D] Santa Claus 2
题意
平面上有 \(n\) 个点,有 \(m\) 个操作,每次操作可以向上下左右移动若干格,问 \(m\) 个操作后的坐标与经过的点的数量(多次经过不算)。
思路
个人认为史上最恶心 D 题,思路不难想,代码就是依托。
容易发现每次移动后要不 \(x\) 坐标不变,要不 \(y\) 坐标不变,于是可以用 \(\text{set}\) 对于每个 \(x\) 坐标和 \(y\) 坐标存下 \(x_i=x\) 和 \(y_i=y\) 的点,这样在每次移动时只需要遍历在 \(x\) 坐标上或在 \(y\) 坐标上的点并删除即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m,sx,sy,ans,lx,ly;
unordered_map<int,int> xx,yy;
map<pair<int,int>,bool> vis;
set<int> mx[200005],my[200005];
signed main() {ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr);cin>>n>>m>>sx>>sy;for(int x,y,i=1;i<=n;i++){cin>>x>>y;if(!xx[x]) xx[x]=++lx;if(!yy[y]) yy[y]=++ly;mx[xx[x]].insert(y);my[yy[y]].insert(x);}vector<int> rem;for(int i=1;i<=m;i++){rem.clear();char s;int x,tx,ty;cin>>s>>x;tx=xx[sx],ty=yy[sy];if(s=='U'){if(!mx[tx].empty())for(auto it=mx[tx].lower_bound(sy);it!=mx[tx].end()&&*it<=sy+x;it++){if(!vis[{sx,*it}])ans++,vis[{sx,*it}]=true;rem.push_back(*it);}for(int v:rem)mx[tx].erase(v);sy+=x;}if(s=='D'){if(!mx[tx].empty())for(auto it=--mx[tx].upper_bound(sy);*it>=sy-x;it--){if(!vis[{sx,*it}])ans++,vis[{sx,*it}]=true;rem.push_back(*it);if(it==mx[tx].begin()) break;}for(int v:rem)mx[tx].erase(v);sy-=x;}if(s=='L'){if(!my[ty].empty())for(auto it=--my[ty].upper_bound(sx);*it>=sx-x;it--){if(!vis[{*it,sy}])ans++,vis[{*it,sy}]=true;rem.push_back(*it);if(it==my[ty].begin()) break;}for(int v:rem)my[ty].erase(v);sx-=x;}if(s=='R'){if(!my[ty].empty())for(auto it=my[ty].lower_bound(sx);it!=my[ty].end()&&*it<=sx+x;it++){if(!vis[{*it,sy}])ans++,vis[{*it,sy}]=true;rem.push_back(*it);}for(int v:rem)my[ty].erase(v);sx+=x;}}cout<<sx<<" "<<sy<<" "<<ans;return 0;
}