简要题意见此:here
题解:
其实不是平面图也可以做,化边为点,边的权值设为删除时间,然后双指针就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
#define y1 y_1
#define y2 y_2
cs int N=1e5+7;
int n,m1,m2,tot,ct1,ct2,ec;
struct edge{int u,v;}e[N<<2|3];
int vl[N*7],tim[N*7];
namespace LCT{
cs int N=::N*7;
#define lc(u) son[u][0]
#define rc(u) son[u][1]
int son[N][2],fa[N],sum[N],sub[N];
bool rev[N];int mx[N];
inline void rever(int u){rev[u]^=1;std::swap(lc(u),rc(u));}
inline void pushdn(int u){
if(rev[u]){
if(lc(u))rever(lc(u));
if(rc(u))rever(rc(u));
rev[u]=0;
}
}
inline void pushup(int u){
sum[u]=sum[lc(u)]+sum[rc(u)]+vl[u]+sub[u];mx[u]=u;
if(tim[mx[lc(u)]]>tim[mx[u]])mx[u]=mx[lc(u)];
if(tim[mx[rc(u)]]>tim[mx[u]])mx[u]=mx[rc(u)];
}
inline bool get(int u){return rc(fa[u])==u;}
inline bool isrt(int u){return lc(fa[u])!=u&&rc(fa[u])!=u;}
inline void Rotate(int u){
int p=fa[u],pp=fa[p],d=get(u);
if(!isrt(p))son[pp][get(p)]=u;
son[p][d]=son[u][!d],son[u][!d]=p;
fa[p]=u,fa[u]=pp,fa[son[p][d]]=p;
pushup(p);pushup(u);
}
void Splay(int u){
static int q[N],qn;q[qn=1]=u;
for(int re p=u;!isrt(p);p=fa[p])q[++qn]=fa[p];
for(int re i=qn;i;--i)pushdn(q[i]);
for(int re p=fa[u];!isrt(u);Rotate(u),p=fa[u])
if(!isrt(p))Rotate(get(u)==get(p)?p:u);pushup(u);
}
void access(int u){
for(int re ch=0;u;u=fa[ch=u]){
Splay(u);if(rc(u))sub[u]+=sum[rc(u)];
if(ch)sub[u]-=sum[ch];rc(u)=ch;
pushup(u);
}
}
void makert(int u){access(u);Splay(u),rever(u);}
int find_rt(int u){
access(u);Splay(u);
while(pushdn(u),lc(u))u=lc(u);
Splay(u);return u;
}
bool iscon(int u,int v){makert(u);return find_rt(v)==u;}
void link(int u,int v){
makert(u);access(v);Splay(v);
fa[u]=v;sub[v]+=sum[u];pushup(v);
}
void cut(int u,int v){
makert(u);access(v);Splay(v);
fa[lc(v)]=0,lc(v)=0,pushup(v),pushup(u);
}
int qsz(int u){access(u);Splay(u);return sum[u];}
int find_e(int u,int v){
makert(u),access(v),Splay(v);
return mx[v];
}
#undef rc
#undef lc
}
int y1[N],y2[N];
int p1[N],p2[N],po[N];
std::vector<int> e1[N],e2[N];
std::vector<int> nd1[N],nd2[N];
int b[N];
signed main(){
#ifdef zxyoi
freopen("mt.in","r",stdin);
#endif
n=gi(),m1=gi(),m2=gi();
tot=n+m1+n+m2;
for(int re i=1;i<=m1;++i)p1[i]=++tot;
for(int re i=1;i<=m2;++i)p2[i]=++tot;
for(int re i=1;i<=n;++i)po[i]=++tot,vl[tot]=1;
for(int re i=1;i<=tot;++i)LCT::pushup(tot);
for(int re i=1;i<=m1;++i)gi(),b[i]=y1[i]=gi();
std::sort(b+1,b+m1+1);ct1=std::unique(b+1,b+m1+1)-b-1;
for(int re i=1;i<=m1;++i){
y1[i]=std::lower_bound(b+1,b+ct1+1,y1[i])-b;
nd1[y1[i]].push_back(i);
}
for(int re i=1;i<n+m1;++i){
int t=gi(),u=gi(),v=gi();
if(t==1){
e[++ec]=(edge){po[u],p1[v]};
e1[v].push_back(ec);tim[ec]=y1[v];
LCT::link(ec,po[u]);LCT::link(ec,p1[v]);
}else {
e[++ec]=(edge){p1[u],p1[v]};
if(y1[u]>y1[v])e1[u].push_back(ec),tim[ec]=y1[u];
else e1[v].push_back(ec),tim[ec]=y1[v];
LCT::link(ec,p1[u]);LCT::link(ec,p1[v]);
}
}
for(int re i=1;i<=m2;++i)gi(),b[i]=y2[i]=gi();
std::sort(b+1,b+m2+1);ct2=std::unique(b+1,b+m2+1)-b-1;
for(int re i=1;i<=m2;++i){
y2[i]=std::lower_bound(b+1,b+ct2+1,y2[i])-b;
nd2[y2[i]].push_back(i);
}
for(int re i=1;i<n+m2;++i){
int t=gi(),u=gi(),v=gi();
if(t==1){
e[++ec]=(edge){po[u],p2[v]};
e2[v].push_back(ec);
}else {
e[++ec]=(edge){p2[u],p2[v]};
if(y2[u]>y2[v])e2[u].push_back(ec);
else e2[v].push_back(ec);
}
}
ll ans=0,all=(ll)m1*m2;
for(int re i1=ct1,i2=1,now=0;i1;--i1){
for(int re u:nd1[i1])
for(int re j:e1[u]){
if(LCT::iscon(j,e[j].u))LCT::cut(j,e[j].u);
if(LCT::iscon(j,e[j].v))LCT::cut(j,e[j].v);
}
while(i2<=ct2&&LCT::qsz(po[1])<n){
for(int re u:nd2[i2])
for(int re j:e2[u]){
if(LCT::iscon(e[j].u,e[j].v)){
int p=LCT::find_e(e[j].u,e[j].v);
LCT::cut(p,e[p].u);
LCT::cut(p,e[p].v);
}
LCT::link(j,e[j].u);
LCT::link(j,e[j].v);
}
now+=nd2[i2++].size();
}
ans+=(ll)nd1[i1].size()*(m2-now);
}
if(ans==0)cout<<"0\n";
else if(ans==all)cout<<"1\n";
else {
ll g=std::__gcd(ans,all);
cout<<ans/g<<"/"<<all/g<<"\n";
}
return 0;
}
再来一份没有化边为点的,跑得居然更慢:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
#define y1 y_1
#define y2 y_2
cs int N=1e5+7;
int n,m1,m2,tot,ct1,ct2,ec;
struct edge{int u,v;}e[N<<2|3];
int tim[N<<2|3],vl[N*3];
namespace LCT{
cs int N=::N*3;
#define lc(u) son[u][0]
#define rc(u) son[u][1]
int son[N][2],fa[N],sum[N],sub[N];
bool rev[N];int mx[N],pr[N],sf[N];
inline void rever(int u){rev[u]^=1;
std::swap(lc(u),rc(u));
std::swap(pr[u],sf[u]);
}
void pushdn(int u){
if(rev[u]){
if(lc(u))rever(lc(u));
if(rc(u))rever(rc(u));
rev[u]=0;
}
}
void pushup(int u){
sum[u]=sum[lc(u)]+sum[rc(u)]+vl[u]+sub[u];mx[u]=0;
(lc(u)&&tim[pr[u]]>tim[mx[u]])&&(mx[u]=pr[u]);
(rc(u)&&tim[sf[u]]>tim[mx[u]])&&(mx[u]=sf[u]);
(tim[mx[lc(u)]]>tim[mx[u]])&&(mx[u]=mx[lc(u)]);
(tim[mx[rc(u)]]>tim[mx[u]])&&(mx[u]=mx[rc(u)]);
}
inline bool get(int u){return rc(fa[u])==u;}
inline bool isrt(int u){return lc(fa[u])!=u&&rc(fa[u])!=u;}
inline void Rotate(int u){
int p=fa[u],pp=fa[p],d=get(u);
if(!isrt(p))son[pp][get(p)]=u;
son[p][d]=son[u][!d],son[u][!d]=p;
fa[p]=u,fa[u]=pp,fa[son[p][d]]=p;
pushup(p);pushup(u);
}
void Splay(int u){
static int q[N],qn;q[qn=1]=u;
for(int re p=u;!isrt(p);p=fa[p])q[++qn]=fa[p];
for(int re i=qn;i;--i)pushdn(q[i]);
for(int re p=fa[u];!isrt(u);Rotate(u),p=fa[u])
if(!isrt(p))Rotate(get(p)==get(u)?p:u);
}
void access(int u){
for(int re ch=0;u;u=fa[ch=u]){
Splay(u);if(rc(u))sub[u]+=sum[rc(u)],rc(u)=0;
if(ch){
sub[u]-=sum[ch];
while(pushdn(ch),lc(ch))ch=lc(ch);
Splay(ch);sf[u]=pr[ch];rc(u)=ch;
}pushup(u);
}
}
void makert(int u){access(u);Splay(u);rever(u);}
int find_rt(int u){
access(u);Splay(u);
while(pushdn(u),lc(u))u=lc(u);
Splay(u);return u;
}
bool iscon(int u,int v){makert(u);return find_rt(v)==u;}
void link(int u,int v,int e){
makert(u),access(v),Splay(v);
fa[u]=v,sub[v]+=sum[u];pr[u]=sf[v]=e;
pushup(u),pushup(v);
}
void cut(int u,int v){
makert(u);access(v);Splay(v);
fa[lc(v)]=0,lc(v)=0,pushup(v),pushup(u);
}
int qsz(int u){access(u);Splay(u);return sum[u];}
int find_e(int u,int v){
makert(u),access(v),Splay(v);
return mx[v];
}
#undef lc
#undef rc
}
bool del[N<<2|3];
int y1[N],y2[N];
int p1[N],p2[N],po[N];
std::vector<int> e1[N],e2[N];
std::vector<int> nd1[N],nd2[N];
int b[N];
signed main(){
#ifdef zxyoi
freopen("mt.in","r",stdin);
#endif
n=gi(),m1=gi(),m2=gi();tot=0;
for(int re i=1;i<=m1;++i)p1[i]=++tot;
for(int re i=1;i<=m2;++i)p2[i]=++tot;
for(int re i=1;i<=n;++i)po[i]=++tot,vl[tot]=1;
for(int re i=1;i<=tot;++i)LCT::pushup(i);
for(int re i=1;i<=m1;++i)gi(),b[i]=y1[i]=gi();
std::sort(b+1,b+m1+1);ct1=std::unique(b+1,b+m1+1)-b-1;
for(int re i=1;i<=m1;++i){
y1[i]=std::lower_bound(b+1,b+ct1+1,y1[i])-b;
nd1[y1[i]].push_back(i);
}
for(int re i=1;i<n+m1;++i){
int t=gi(),u=gi(),v=gi();
if(t==1){
e[++ec]=(edge){po[u],p1[v]};
e1[v].push_back(ec);tim[ec]=y1[v];
LCT::link(po[u],p1[v],ec);
}else {
e[++ec]=(edge){p1[u],p1[v]};
if(y1[u]>y1[v])e1[u].push_back(ec),tim[ec]=y1[u];
else e1[v].push_back(ec),tim[ec]=y1[v];
LCT::link(p1[u],p1[v],ec);
}
}
for(int re i=1;i<=m2;++i)gi(),b[i]=y2[i]=gi();
std::sort(b+1,b+m2+1);ct2=std::unique(b+1,b+m2+1)-b-1;
for(int re i=1;i<=m2;++i){
y2[i]=std::lower_bound(b+1,b+ct2+1,y2[i])-b;
nd2[y2[i]].push_back(i);
}
for(int re i=1;i<n+m2;++i){
int t=gi(),u=gi(),v=gi();
if(t==1){
e[++ec]=(edge){po[u],p2[v]};
e2[v].push_back(ec);
}else {
e[++ec]=(edge){p2[u],p2[v]};
if(y2[u]>y2[v])e2[u].push_back(ec);
else e2[v].push_back(ec);
}
}
ll ans=0,all=(ll)m1*m2;
for(int re i1=ct1,i2=1,now=0;i1;--i1){
for(int re u:nd1[i1])
for(int re j:e1[u]){
if(!del[j])LCT::cut(e[j].u,e[j].v);
}
while(i2<=ct2&&LCT::qsz(po[1])<n){
for(int re u:nd2[i2])
for(int re j:e2[u]){
if(LCT::iscon(e[j].u,e[j].v)){
int p=LCT::find_e(e[j].u,e[j].v);
LCT::cut(e[p].u,e[p].v);
del[p]=true;
}
LCT::link(e[j].v,e[j].u,j);
}
now+=nd2[i2++].size();
}
ans+=(ll)nd1[i1].size()*(m2-now);
}
if(ans==0)cout<<"0\n";
else if(ans==all)cout<<"1\n";
else {
ll g=std::__gcd(ans,all);
cout<<ans/g<<"/"<<all/g<<"\n";
}
return 0;
}