3
20
2016
0

[bzoj]3772: 精神污染

传送门-->http://www.lydsy.com/JudgeOnline/problem.php?id=3772

坑没怎么填, 写篇题解 凑凑数

促使我写这题题解的动力是网上题解都是什么$dfs$序+主席树,看到都忍不住笑出声


首先明确,一条路径被另外一条路径包含时只有两种情况,设两条路径$(x,y)$$(u,v)$,判断$(x,y)$是否被$(u,v)$包含,强制$y$深度小于$x$,则分情况:

$I$$y$$x$的祖先,$z$$x$$y$路径上$y$下面那个点,则可以知道,包含它的路径一头在$x$的子树里,另一头不在$z$的子树里,于是可以分成两个矩形

$II$$x$$y$不 构成先辈关系,则一头在$x$的子树里,另一头在$y$的子树里,可以构成一个矩形

然后就把所有矩形映射到二维平面上,再把所有路径两头作为二维点同样映射到平面上,于是一条路径$(x,y)$被包含的数目就是平面上二维点被几个矩形包含,所以$Ans$便为所有二维点被几个矩形包含的和减去的二维点个数(因为同时有同一条路径构出的矩形和二维点),扫描线即可

#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
#define nc() getchar()
inline int read(){
	int x=0;char ch=nc();for(;ch<'0'||ch>'9';ch=nc());
	for(;ch<='9'&&ch>='0';x=x*10+ch-48,ch=nc());return x;
}
#define N 100010
int i,j,k,m,n,x,y,cnt,last[N],fa[N],top[N],t,in[N],ot[N],sz[N],son[N],now,dep[N],rk[N],m2,m1,ans[N<<1],v[N];
struct edge{int to,next;}e[N<<1];ll Ans,nm;
struct line{int h,l,r,v;bool operator <(const line&b)const{return h<b.h;}}T[N<<2];
struct point{int x,y,id;bool operator <(const point&b)const{return x<b.x;}}C[N<<1];
inline void add(int u,int v){
	e[++cnt]=(edge){v,last[u]},last[u]=cnt;
	e[++cnt]=(edge){u,last[v]},last[v]=cnt;
}
void dfs1(int x,int d){
	dep[x]=d,sz[x]=1;
	for(int i=last[x],y;i;i=e[i].next)if((y=e[i].to)!=fa[x]){
		fa[y]=x,dfs1(y,d+1),sz[x]+=sz[y];
		if(sz[y]>sz[son[x]])son[x]=y;
	}
}void dfs2(int x,int d){
	top[x]=d,rk[in[x]=++now]=x;if(son[x])dfs2(son[x],d);
	for(int i=last[x],y;i;i=e[i].next)if((y=e[i].to)!=fa[x]&&y!=son[x])dfs2(y,y);ot[x]=now;
}
inline int up(int x,int k){
	if(k<0)return x;
	while(top[x]!=1)if(dep[x]-dep[top[x]]<k)k-=dep[x]-dep[top[x]]+1,x=fa[top[x]];else return rk[in[x]-k];
	return rk[in[x]-k];
}
inline void Add(int x,int d){for(;x<=n;v[x]+=d,x+=x&-x);}
inline int ask(int x){int ret=0;for(;x;ret+=v[x],x-=x&-x);return ret;}
int main(){
	for(n=read(),m=read(),i=1;i<n;++i)add(read(),read());
	for(dfs1(1,0),dfs2(1,1),i=1;i<=m;++i){
		x=read(),y=read();
		if(dep[x]<dep[y])swap(x,y);
		C[++m2]=(point){in[x],in[y],i};if(x!=y)C[++m2]=(point){in[y],in[x],i};
		if(in[x]>=in[y]&&in[x]<=ot[y]){
			t=(x!=y),y=up(x,dep[x]-dep[y]-1);
			int u=in[x],v=ot[x],l=1,r=in[y]-t;
			if(l<=r)T[++m1]=(line){u,l,r,1},T[++m1]=(line){v+1,l,r,-1};
			l=ot[y]+1,r=n;
			if(l<=r)T[++m1]=(line){u,l,r,1},T[++m1]=(line){v+1,l,r,-1};
		}else{
			int u=in[x],v=ot[x],l=in[y],r=ot[y];
			if(l<=r)T[++m1]=(line){u,l,r,1},T[++m1]=(line){v+1,l,r,-1};
		}
	}
	for(sort(T+1,T+m1+1),sort(C+1,C+m2+1),i=j=1;i<=m2;++i){
		while(j<=m1&&T[j].h<=C[i].x)Add(T[j].l,T[j].v),Add(T[j].r+1,-T[j].v),++j;
		ans[C[i].id]+=ask(C[i].y);
	}
	for(i=1;i<=m;++i)Ans+=ans[i];Ans-=m,nm=1ll*m*(m-1)/2;
	ll gcd=__gcd(Ans,nm);printf("%lld/%lld\n",Ans/gcd,nm/gcd);
}

 

loading...

Category: bzoj | Tags: DFS序 扫描线 | Read Count: 635

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com