LOJ2760题解
请叫我挂分大师。
没清空导致 100pts->0pts 数组还开大了 MLE,不愧是我。
对于连通块计数,可以考虑的一个东西叫做平面图欧拉定理:\(V+F=E+2\)。
其中 \(V\) 是节点数,\(F\) 是区域数,\(E\) 是边数。
证明就是说,考虑一棵树一定是平面图,加上一条边成环之后一定会多出来一个区域。
然后再加上最外面有一个区域,答案就是 \(F=E-V+1+1\)。
回到这个题,容易发现这道题的图是一个平面图,但是可能不连通。
对于不连通非常好解决,假设我们只计数内部的区域那么答案就是 \(E-V+1\),然后不连通的情况下,新生成的区域只会和自身所在连通块有关。所以答案是 \(\sum E-\sum V+F\),这里的 \(F\) 表示连通块的数量。
可以发现,只需要计算每条裁剪线与哪些相交了即可计算出点数和边数,离线线段树即可统计。
连通块数量略有麻烦。考虑相交的两条裁剪线连一条边,这个过程可以使用上述计算边数和点数类似的方法线段树优化建图。
想到了平面图欧拉定理就不难了其实,主要问题是有点缝+难写,比如这个人清空的长度出问题了就挂了巨大多分。
记得把坐标离散化。
#include<algorithm>
#include<cstdio>
#include<cctype>
#include<vector>
namespace SOLVE{
const int M=2e5+114;
int n,m,W,H,k,lim,ege,tot,x1[M],y1[M],x2[M],y2[M],h[M*80];int len,lsh[M];bool vis[M*80];
std::vector<int>Add[M],Del[M],Qry[M],x,y;int sum[M<<2];
struct Edge{
int v,nx;
}e[M*80];
inline void AE(const int&u,const int&v){
e[++ege]=(Edge){v,h[u]};h[u]=ege;
}
inline int read(){
int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
struct SOG{
int id[M<<2];
inline void Build(const int&u,const int&L=1,const int&R=lim){
id[u]=-1;if(L==R)return;const int&mid=L+R>>1;Build(u<<1,L,mid);Build(u<<1|1,mid+1,R);
}
inline void update(const int&u){
if(!~id[u<<1]&&!~id[u<<1|1])id[u]=-1;else id[u]=++tot;
if(~id[u<<1])AE(id[u],id[u<<1]);if(~id[u<<1|1])AE(id[u],id[u<<1|1]);
}
inline void Ins(const int&u,const int&x,const int&w,const int&L=1,const int&R=lim){
if(L==R)return void(id[u]=w);const int&mid=L+R>>1;
x<=mid?Ins(u<<1,x,w,L,mid):Ins(u<<1|1,x,w,mid+1,R);update(u);
}
inline void Lnk(const int&u,const int&l,const int&r,const int&v,const int&L=1,const int&R=lim){
if(l>R|L>r)return;if(l<=L&&R<=r)return~id[u]&&(AE(v,id[u]),0),void();
const int&mid=L+R>>1;Lnk(u<<1,l,r,v,L,mid);Lnk(u<<1|1,l,r,v,mid+1,R);
}
}sog;
struct SGT{
int BIT[M];
inline void Add(int x,const int&w){
while(x<=lim)BIT[x]+=w,x+=x&-x;
}
inline int Qry(int x){
int sum(0);while(x>=1)sum+=BIT[x],x-=x&-x;return sum;
}
inline int Qry(const int&L,const int&R){
return Qry(R)-Qry(L-1);
}
}sgt;
inline void DFS(const int&u){
vis[u]=true;for(int E=h[u];E;E=e[E].nx)if(!vis[e[E].v])DFS(e[E].v);
}
inline void main(){
long long ans(0);W=read();H=read();k=read();tot=k+4;
for(int i=1;i<=k;++i){
x1[i]=read();y1[i]=read();x2[i]=read();y2[i]=read();
if(x1[i]==x2[i])x.push_back(i);if(y1[i]==y2[i])y.push_back(i);
}
++k;x1[k]=0;y1[k]=0;x2[k]=W;y2[k]=0;y.push_back(k);
++k;x1[k]=W;y1[k]=0;x2[k]=W;y2[k]=H;x.push_back(k);
++k;x1[k]=0;y1[k]=H;x2[k]=W;y2[k]=H;y.push_back(k);
++k;x1[k]=0;y1[k]=0;x2[k]=0;y2[k]=H;x.push_back(k);
len=0;for(int i=1;i<=k;++i)lsh[++len]=x1[i],lsh[++len]=x2[i];
std::sort(lsh+1,lsh+len+1);n=std::unique(lsh+1,lsh+len+1)-lsh-1;
for(int i=1;i<=k;++i){
x1[i]=std::lower_bound(lsh+1,lsh+n+1,x1[i])-lsh;x2[i]=std::lower_bound(lsh+1,lsh+n+1,x2[i])-lsh;
}
len=0;for(int i=1;i<=k;++i)lsh[++len]=y1[i],lsh[++len]=y2[i];
std::sort(lsh+1,lsh+len+1);m=std::unique(lsh+1,lsh+len+1)-lsh-1;
for(int i=1;i<=k;++i){
y1[i]=std::lower_bound(lsh+1,lsh+m+1,y1[i])-lsh;y2[i]=std::lower_bound(lsh+1,lsh+m+1,y2[i])-lsh;
}
lim=m;sog.Build(1);for(int i=1;i<=lim;++i)sgt.BIT[i]=0;
for(int&id:y)Add[x1[id]].push_back(id),Del[x2[id]+1].push_back(id);
for(int&id:x)Qry[x1[id]].push_back(id);
for(int i=1;i<=n;++i){
for(int&id:Del[i])sog.Ins(1,y1[id],-1),sgt.Add(y1[id],-1);
for(int&id:Add[i])sog.Ins(1,y1[id],id),sgt.Add(y1[id],1);
for(int&id:Qry[i]){
int w=sgt.Qry(y1[id],y2[id]);sog.Lnk(1,y1[id],y2[id],id);if(w)--ans;
}
}
for(int i=1;i<=m;++i){
std::vector<int>().swap(Add[i]);std::vector<int>().swap(Del[i]);std::vector<int>().swap(Qry[i]);
}
lim=n;sog.Build(1);for(int i=1;i<=lim;++i)sgt.BIT[i]=0;
for(int&id:x)Add[y1[id]].push_back(id),Del[y2[id]+1].push_back(id);
for(int&id:y)Qry[y1[id]].push_back(id);
for(int i=1;i<=m;++i){
for(int&id:Del[i])sog.Ins(1,x1[id],-1),sgt.Add(x1[id],-1);
for(int&id:Add[i])sog.Ins(1,x1[id],id),sgt.Add(x1[id],1);
for(int&id:Qry[i]){
int w=sgt.Qry(x1[id],x2[id]);sog.Lnk(1,x1[id],x2[id],id);if(w)ans+=w-1;
}
}
for(int i=1;i<=k;++i)if(e[h[i]].v&&!vis[i])DFS(i),++ans;printf("%lld",ans);
}
}
signed main(){
SOLVE::main();
}
//F+V=E+2
//\sum E-V+1=\sum E-\sum V-cnt