2021牛客多校6 - Hopping Rabbit(矩形取模+扫描线)
題目鏈接:點擊查看
題目大意:二維平面給出 nnn 個矩形,現在要求找到一個點 (x+0.5,y+0.5)(x+0.5,y+0.5)(x+0.5,y+0.5),滿足對于任意的 (x+0.5+k1d,y+0.5+k2d)(x+0.5+k_1d,y+0.5+k_2d)(x+0.5+k1?d,y+0.5+k2?d) 都不會出現在任意一個矩形中
題目分析:假設我們找到的目標點為 (x,y)(x,y)(x,y),不難每次移動目標點,對于每個矩形來說,對 ddd 取模后的相對坐標都是不變的,所以我們不妨將每個矩形都對 ddd 取模
矩形取模的話,可以先對坐標取模,再根據取模后的大小分類討論,一個矩形取模后至多會分成四個矩形
然后就是需要在 [0,d?1]×[0,d?1][0,d-1] \times [0,d-1][0,d?1]×[0,d?1] 的坐標系中找到一個滿足條件的點,其不屬于任意一個矩形之中
翻譯一下就在矩形并的補集中找到一個點即可,關于矩形并問題的求解直接用掃描線來寫就好啦
有一個細節就是關于區間與點的問題,掃描線維護的是區間而不是端點,兩者之間的轉換有好多種方法,可以根據自己的喜好選擇,這里給出三種可行方案:
這里我選擇了第三種方法,然后用掃描線維護區間內所有點被覆蓋的最小次數,當且僅當這個最小次數等于 000 時,說明了至少有一個點是沒有被覆蓋的,直接 nlognnlognnlogn 掃描所有的點,找到答案后退出即可
代碼:
// Problem: Hopping Rabbit // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/11257/H // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #define lowbit(x) x&-x using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100; int n,d; struct Line {int downy,upy,into; }; vector<Line>node[N]; struct Node {int l,r,mmin,lazy; }tree[N<<2]; void pushup(int k) {tree[k].mmin=min(tree[k<<1].mmin,tree[k<<1|1].mmin); } void pushdown(int k) {if(tree[k].lazy) {int lz=tree[k].lazy;tree[k].lazy=0;tree[k<<1].mmin+=lz;tree[k<<1|1].mmin+=lz;tree[k<<1].lazy+=lz;tree[k<<1|1].lazy+=lz;} } void build(int k,int l,int r) {tree[k]={l,r,0,0};if(l==r) {return;}int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r); } void update(int k,int l,int r,int val) {if(tree[k].l>r||tree[k].r<l) {return;}if(tree[k].l>=l&&tree[k].r<=r) {tree[k].mmin+=val;tree[k].lazy+=val;return;}pushdown(k);update(k<<1,l,r,val);update(k<<1|1,l,r,val);pushup(k); } void get_ans(int k,int x) {if(tree[k].l==tree[k].r) {if(tree[k].mmin==0) {puts("YES");cout<<x<<' '<<tree[k].l<<endl;exit(0);}return;}pushdown(k);get_ans(k<<1,x);get_ans(k<<1|1,x); } void md(int& x) {x%=d;if(x<0) {x+=d;} } void add(int x1,int x2,int y1,int y2) {node[x1].push_back({y1,y2,1});node[x2+1].push_back({y1,y2,-1}); } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);read(n),read(d);for(int i=1;i<=n;i++) {int x1,y1,x2,y2;read(x1),read(y1),read(x2),read(y2);x2--,y2--;if(x2-x1+1>=d) x1=0,x2=d-1;if(y2-y1+1>=d) y1=0,y2=d-1;md(x1),md(y1),md(x2),md(y2);if(x1<=x2) {if(y1<=y2) {add(x1,x2,y1,y2);} else {add(x1,x2,y1,d-1),add(x1,x2,0,y2);}} else {if(y1<=y2) {add(0,x2,y1,y2),add(x1,d-1,y1,y2);} else {add(0,x2,y1,d-1),add(0,x2,0,y2),add(x1,d-1,y1,d-1),add(x1,d-1,0,y2);}}}build(1,0,d-1);for(int i=0;i<d;i++) {for(auto it:node[i]) {update(1,it.downy,it.upy,it.into);}if(tree[1].mmin==0) {get_ans(1,i);}}puts("NO");return 0; }總結
以上是生活随笔為你收集整理的2021牛客多校6 - Hopping Rabbit(矩形取模+扫描线)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1549F1
- 下一篇: 2021牛客多校6 - Defend Y