题解:P10278 [USACO24OPEN] Painting Fence Posts S
hqc20230131 · · 题解
先考虑建图,我们把所有横坐标相同的点放在一起,按照它们的纵坐标排序,设下标为
之后再选择一个点跑深搜,把每一个遍历到的点加入,相当于破环为链。
处理询问,假设现在我们给定了
后面直接前缀和即可。
:::success[代码]
#include<bits/stdc++.h>
#define N 100005
#define M 200005
using namespace std;
typedef long long ll;
struct edge{int to,w,nex;};
int n,m,x[M],y[M],hea[M],cnt,p[M],tot,id[M];
ll sum[M],ans[M],last,d[M];
bool vis[M];
edge g[M<<1];
map<pair<int,int>,int> mp;
map<int,vector<pair<int,int> > > gx,gy,px,py;
void add(int fro,int to,int w){g[++cnt]={to,w,hea[fro]},hea[fro]=cnt;}
void dfs(int u,int h)
{
last=h;
if(vis[u])
return;
vis[u]=1;
p[++tot]=u;
id[u]=tot;
sum[tot]=h;
for(int i=hea[u],v=g[i].to,w=g[i].w;i;i=g[i].nex,v=g[i].to,w=g[i].w)
dfs(v,w);
}
ll dis(int i,int j)
{
if(sum[i]>sum[j])
swap(i,j);
return min(sum[j]-sum[i],sum[tot]-sum[j]+sum[i]);
}
void calc(int l,int r)
{
// cout<<"["<<l<<' '<<r<<"] ";
d[l]++;
d[r+1]--;
}
int main()
{
// freopen("sample.in","r",stdin);
// freopen("sample.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>x[i]>>y[i];
gx[x[i]].push_back({y[i],i});
gy[y[i]].push_back({x[i],i});
mp[{x[i],y[i]}]=i;
}
for(auto i:gx)
{
auto &k=i.second;
stable_sort(k.begin(),k.end());
int len=k.size();
for(int j=0;j<len;j+=2)
{
int h=k[j+1].first-k[j].first;
add(k[j].second,k[j+1].second,h);
add(k[j+1].second,k[j].second,h);
px[i.first].push_back({k[j].first,k[j+1].first});
}
}
for(auto i:gy)
{
auto &k=i.second;
stable_sort(k.begin(),k.end());
int len=k.size();
for(int j=0;j<len;j+=2)
{
int h=k[j+1].first-k[j].first;
add(k[j].second,k[j+1].second,h);
add(k[j+1].second,k[j].second,h);
py[i.first].push_back({k[j].first,k[j+1].first});
}
}
dfs(1,0);
p[++tot]=1;
sum[tot]=last;
for(int i=1;i<=tot;i++)
sum[i]+=sum[i-1];
// for(int i=1;i<=tot;i++)
// cout<<p[i]<<' ';cout<<'\n';
for(int _=1;_<=n;_++)
{
int x1,x2,y1,y2;
cin>>x1>>y1>>x2>>y2;
int flag1=0,flag2=0;
ll a=0,b=0,c=0,d=0;
int l,r;
if(mp[{x1,y1}])
l=r=mp[{x1,y1}];
else
{
auto it=upper_bound(px[x1].begin(),px[x1].end(),make_pair(y1,0));
if(it!=px[x1].begin()&&(--it)->second>=y1)
{
l=mp[{x1,it->first}];
r=mp[{x1,it->second}];
a=y1-it->first;
b=it->second-y1;
if(y1!=it->first&&y1!=it->second)
flag1=1;
}
else
{
it=upper_bound(py[y1].begin(),py[y1].end(),make_pair(x1,0));
it--;
l=mp[{it->first,y1}];
r=mp[{it->second,y1}];
a=x1-it->first;
b=it->second-x1;
if(x1!=it->first&&x1!=it->second)
flag1=1;
}
}
int p,q;
if(mp[{x2,y2}])
p=q=mp[{x2,y2}];
else
{
auto it=upper_bound(px[x2].begin(),px[x2].end(),make_pair(y2,0));
if(it!=px[x2].begin()&&(--it)->second>=y2)
{
p=mp[{x2,it->first}];
q=mp[{x2,it->second}];
c=y2-it->first;
d=it->second-y2;
if(y2!=it->first&&y2!=it->second)
flag2=1;
}
else
{
it=upper_bound(py[y2].begin(),py[y2].end(),make_pair(x2,0));
it--;
p=mp[{it->first,y2}];
q=mp[{it->second,y2}];
c=x2-it->first;
d=it->second-x2;
if(x2!=it->first&&x2!=it->second)
flag2=1;
}
}
if(l==p&&q==r&&flag1&&flag2)
{
// cout<<"Null\n";
continue;
}
l=id[l];
r=id[r];
p=id[p];
q=id[q];
// cout<<l<<' '<<r<<' '<<p<<' '<<q<<" : ";
ll h=min(min(dis(l,p)+a+c,dis(l,q)+a+d),min(dis(r,p)+b+c,dis(r,q)+b+d));
if(dis(l,p)+a+c==h)
{
if(sum[l]>sum[p])swap(l,p);
if(sum[p]-sum[l]>sum[tot]-sum[p]+sum[l])
calc(1,l),calc(p,tot);
else
calc(l,p);
}
else if(dis(l,q)+a+d==h)
{
if(sum[l]>sum[q])swap(l,q);
if(sum[q]-sum[l]>sum[tot]-sum[q]+sum[l])
calc(1,l),calc(q,tot);
else
calc(l,q);
}
else if(dis(r,p)+b+c==h)
{
if(sum[r]>sum[p])swap(r,p);
if(sum[p]-sum[r]>sum[tot]-sum[p]+sum[r])
calc(1,r),calc(p,tot);
else
calc(r,p);
}
else if(dis(r,q)+b+d==h)
{
if(sum[r]>sum[q])swap(r,q);
if(sum[q]-sum[r]>sum[tot]-sum[q]+sum[r])
calc(1,r),calc(q,tot);
else
calc(r,q);
}
// cout<<'\n';
}
for(int i=1;i<=tot;i++)
d[i]+=d[i-1];
for(int i=1;i<tot;i++)
ans[p[i]]=d[i];
for(int i=1;i<=m;i++)
cout<<ans[i]<<'\n';
return 0;
}
:::