2021牛客暑期多校训练营6H Hopping Rabbit(扫描线)
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营6H Hopping Rabbit(扫描线)相关的知识,希望对你有一定的参考价值。
H Hopping Rabbit
题意:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e5+10;
//扫描线:从左往右扫
struct Scan{ int l, r, x;};
vector<Scan>v[maxn]; //v[i]:第i列的线段(自带桶排序)
void add(int x1, int x2, int y1, int y2){
v[x1].push_back({y1,y2,1}); //左边
v[x2+1].push_back({y1,y2,-1});//右边
}
//线段树:维护区间被覆盖次数s(区间加),区间被截长度len(即多少位置s有值)
#define lch (p<<1)
#define rch (p<<1|1)
struct Sgt{ int s, len; }tr[maxn];
void push_up(int p, int l, int r){ //[l,r]每次都传递一下就不用建树啦
if(tr[p].s!=0)tr[p].len=r-l+1; //被覆盖完全,更新长度
else if(l==r)tr[p].len=0;
else tr[p].len=tr[lch].len+tr[rch].len;//由子节点更新被截长度
}
void update(int p, int l, int r, int L, int R, int c){//区间[L,R]+=c
if(r<L || l>R)return ;
if(L<=l && r<=R){
tr[p].s += c; //懒标记
push_up(p,l,r);
return ;
}
int mid = (l+r)>>1;
update(lch,l,mid, L,R,c);
update(rch,mid+1,r, L,R,c);
push_up(p,l,r);
}
int gety(int p, int l, int r){//找到空着的位置
if(tr[p].len==0)return l; //找到了
int mid = (l+r)>>1;
if(tr[lch].len<mid-l+1)return gety(lch,l,mid);
else return gety(rch,mid+1,r);
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, d; cin>>n>>d;
for(int i = 1; i <= n; i++){
int x1, y1, x2, y2;
cin>>x1>>y1>>x2>>y2;
x2--, y2--;
if(x2-x1+1>=d){ x1=0, x2=d-1;}//大于[0,d-1]的部分不要了
if(y2-y1+1>=d){ y1=0, y2=d-1;}
x1=(x1%d+d)%d; y1=(y1%d+d)%d;//移动到[0,d-1]来
x2=(x2%d+d)%d; y2=(y2%d+d)%d;
if(x1<=x2){
if(y1<=y2)add(x1,x2,y1,y2);
else add(x1,x2,0,y2),add(x1,x2,y1,d-1);//拆分成两个矩形放入[0,d-1]位置
}else{
if(y1<=y2) add(0,x2,y1,y2),add(x1,d-1,y1,y2);
else add(0,x2,0,y2),add(x1,d-1,y1,d-1),add(0,x2,y1,d-1),add(x1,d-1,0,y2);//拆分成四个矩形放入[0,d-1]位置
}
}
for(int i = 0; i < d; i++){//扫描每一条纵坐标轴
for(Scan line: v[i]){ //把所有的线放入线段树
update(1,0,d-1, line.l,line.r,line.x);
}
if(tr[1].len < d){//如果当前所有的和长度加起来小于d,那么意味着有空的位置
cout<<"YES\\n";
cout<<i<<" "<<gety(1,0,d-1)<<"\\n";
return 0;
}
}
cout<<"NO\\n";
return 0;
}
以上是关于2021牛客暑期多校训练营6H Hopping Rabbit(扫描线)的主要内容,如果未能解决你的问题,请参考以下文章