USACO open 2024 银组 T2
EnofTaiPeople · · 题解
考虑如何快速通过银组。
首先题目没有按逆时针顺序给定栅栏,考虑建出这个环。
分析性质,将对于横坐标相同,纵坐标第
注意要对于每个横纵坐标开一个 std::set 来存储。
接下来,对于每个询问点,尝试在循环链表中插入这些点,使用 set 求出前驱后继即可。
然后断环成链,对于每次询问更改差分数组,最后再做一遍前缀和即可,时间
int T,n,K,m,ct,mp[N],to[N],pr[N],sf[N];
#define MP(x) lower_bound(mp+1,mp+m+1,x)-mp
struct dat{
int x,y;
void mc(){
x=MP(x),y=MP(y);
}
int dst(dat &p){
return abs(mp[x]-mp[p.x])+abs(mp[y]-mp[p.y]);
}
}d[N];
set<pair<int,int> >tx[N],ty[N];
int upd(int x,int y){
auto it=tx[x].lower_bound(mkp(y,0));
int p;
if(it!=tx[x].end()){
if(it->first==y)return it->second;
p=it->second;
if(d[pr[p]].x==x&&d[pr[p]].y<=y){
d[++ct]={x,y};
to[pr[ct]=pr[p]]=ct;
pr[to[ct]=p]=ct;goto lc1;
}
if(d[to[p]].x==x&&d[to[p]].y<=y){
d[++ct]={x,y};
pr[to[ct]=to[p]]=ct;
to[pr[ct]=p]=ct;goto lc1;
}
}
it=ty[y].lower_bound(mkp(x,0));
p=it->second;
if(d[pr[p]].y==y&&d[pr[p]].x<=x){
d[++ct]={x,y};
to[pr[ct]=pr[p]]=ct;
pr[to[ct]=p]=ct;goto lc1;
}
if(d[to[p]].y==y&&d[to[p]].x<=x){
d[++ct]={x,y};
pr[to[ct]=to[p]]=ct;
to[pr[ct]=p]=ct;goto lc1;
}
lc1:tx[x].emplace(y,ct);
ty[y].emplace(x,ct);
return ct;
}
struct D2{
int x,y,l,r;
void mc(){x=upd(MP(x),MP(y)),y=upd(MP(l),MP(r));}
}d2[N];
ll v[N];
vector<int>lk[N];
void dfs(int x){
for(int y:lk[x])
if(x!=to[y]&&!pr[y]){
pr[to[x]=y]=x;
if(!to[y])dfs(y);
}
}
int main(){
ios::sync_with_stdio(false),cin.tie(0);
int i,j,k,l,r,x,y,z;ll v1,v2;
cin>>T>>n;
for(x=1;x<=n;++x){
cin>>l>>r;
mp[++m]=l,mp[++m]=r;
d[x]={l,r};
}
for(i=1;i<=T;++i){
cin>>x>>y>>l>>r;
mp[++m]=x,mp[++m]=y;
mp[++m]=l,mp[++m]=r;
d2[i]={x,y,l,r};
}
sort(mp+1,mp+m+1),m=unique(mp+1,mp+m+1)-mp-1;
for(x=1,ct=n;x<=n;++x){
d[x].mc();
tx[d[x].x].emplace(d[x].y,x);
ty[d[x].y].emplace(d[x].x,x);
}
for(x=1;x<=m;++x){
l=0;
for(auto &p:tx[x]){
r=p.second;
if(l){
lk[l].push_back(r);
lk[r].push_back(l);l=0;
}else l=r;
}
l=0;
for(auto &p:ty[x]){
r=p.second;
if(l){
lk[l].push_back(r);
lk[r].push_back(l);l=0;
}else l=r;
}
}
dfs(1);
// for(x=1;x<=ct;++x)printf("x:%d pr:%d to:%d\n",x,pr[x],to[x]);puts("");
// return 0;
for(i=1;i<=T;++i)d2[i].mc();
for(x=to[1];;x=to[x]){
v[x]=v[pr[x]]+d[x].dst(d[pr[x]]);
// printf("%d ",x);
if(x==1)break;
}
for(i=1;i<=T;++i){
l=d2[i].x,r=d2[i].y;
if(v[l]>v[r])swap(l,r);
// printf("l:%d r:%d\n",l,r);
if((v[r]-v[l])*2>v[1]){
++sf[to[1]],--sf[to[l]];
++sf[r];
}else{
++sf[l];
if(r!=1)--sf[to[r]];
}
}
for(x=to[to[1]];;x=to[x]){
sf[x]+=sf[pr[x]];
if(x==1)break;
}
for(x=1;x<=n;++x)printf("%d\n",sf[x]);
return 0;
}