【校内模拟】坦克(LCT)

简要题意见此: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值