列表

详情


NC20948. 小睿睿的方案

描述

小睿睿虽然已经是人生赢家了,但当他看见学校里其他人秀恩爱时仍旧会十分不满。他的学校有n个教室,教室间有n-1条路径且任意教室互相联通,每天他和小熙熙会选择在两个不同的教室(i,j)间的简单路径上秀恩爱。学校里一共有m对情侣,每对情侣中的两个人分别在教室A,B(A!=B),如果他们秀恩爱时经过的教室里存在任意一对情侣,这种秀恩爱的方案就是不合法的,求合法的无序点对数

无序点对:(i,j)与(j,i)视作同一对

输入描述

第1行,2个整数n,m

第2至n行,每行两个整数a,b,表示a,b间存在一条边

之后m行,每行两个整数a,b,表示有一对情侣分别在教室a和教室b

输出描述

一行一个整数,表示答案

示例1

输入:

8 3
1 2
1 3
4 8
2 4
2 5
3 6
3 7
2 3
4 8
6 7

输出:

11

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 546ms, 内存消耗: 31828K, 提交时间: 2019-02-22 20:39:14

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cassert>

typedef long long ll;
typedef unsigned long long ull;

using namespace std;

const int MAXN=1E5+10;

namespace Segment_Tree{
	int t[MAXN<<3],cov[MAXN<<3];

	void pushup(int x,int l,int r)
	{
		if(cov[x]) t[x]=r-l+1;
		else t[x]=t[x<<1]+t[x<<1|1];
	}

	void change(int x,int l,int r,int cl,int cr,int dlt)
	{
		if(cl<=l&&r<=cr) return cov[x]+=dlt,pushup(x,l,r),void();
		int mid=(l+r)>>1;
		if(cl<=mid) change(x<<1,l,mid,cl,cr,dlt);
		if(cr>mid)  change(x<<1|1,mid+1,r,cl,cr,dlt);
		pushup(x,l,r);
	}
}

struct OPT{
	int x,l,r,f;

	bool operator < (const OPT &rhs) const {return x<rhs.x;}
}op[MAXN*16];

vector<int> T[MAXN];
int cnt,jmp[MAXN][18],dep[MAXN],dfn[MAXN],dft,siz[MAXN],n,m;
ll Ans;

bool inside(int x,int y){return dfn[x]<=dfn[y]&&dfn[y]<=dfn[x]+siz[x]-1;}//y in x

void dfs(int x,int fa)
{
	siz[x]=1;
	dfn[x]=++dft;
	jmp[x][0]=fa;dep[x]=dep[fa]+1;
	for(int v:T[x])
		if(v!=fa)
			dfs(v,x),siz[x]+=siz[v];
}

void solve()
{
	sort(op+1,op+1+cnt);
	for(int i=1;i<=cnt;i++)
	{
		Ans+=1ll*Segment_Tree::t[1]*(op[i].x-op[i-1].x);
		Segment_Tree::change(1,1,n,op[i].l,op[i].r,op[i].f);
	}
}

void add_rec(int x1,int y1,int x2,int y2)
{
	if(x1>x2||y1>y2) return;
	x1=max(1,x1);x1=min(x1,n);
	y1=max(1,y1);y1=min(y1,n);
	x2=max(1,x2);x2=min(x2,n);
	y2=max(1,y2);y2=min(y2,n);
	op[++cnt]=(OPT){x1,y1,y2,1};
	op[++cnt]=(OPT){x2+1,y1,y2,-1};
}

int Nxt(int x,int y)
{
	for(int j=17;~j;j--)
		if(dep[jmp[x][j]]>dep[y])
			x=jmp[x][j];
	return x;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,u,v;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		T[u].push_back(v);
		T[v].push_back(u);
	}
	dfs(1,0);
	for(int j=1;j<=17;j++)
		for(int i=1;i<=n;i++)
			jmp[i][j]=jmp[jmp[i][j-1]][j-1];
	for(int i=1,u,v;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		if(dep[u]>dep[v]) swap(u,v);
		if(inside(u,v))
		{
			int p=Nxt(v,u);
			add_rec(dfn[v],1,dfn[v]+siz[v]-1,dfn[p]-1);
			add_rec(1,dfn[v],dfn[p]-1,dfn[v]+siz[v]-1);
			add_rec(dfn[v],dfn[p]+siz[p],dfn[v]+siz[v]-1,n);
			add_rec(dfn[p]+siz[p],dfn[v],n,dfn[v]+siz[v]-1);
		}
		else
		{
			add_rec(dfn[u],dfn[v],dfn[u]+siz[u]-1,dfn[v]+siz[v]-1);
			add_rec(dfn[v],dfn[u],dfn[v]+siz[v]-1,dfn[u]+siz[u]-1);
		}
	}
	for(int i=1;i<=n;i++) add_rec(i,i,i,i);
	solve();
	printf("%lld\n",(1ll*n*n-Ans)/2);
}

C++11(clang++ 3.9) 解法, 执行用时: 459ms, 内存消耗: 35812K, 提交时间: 2019-03-10 15:09:16

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node
{
	ll sum,cnt;
}tr[400005];
ll n,m,i,u,v,dfn[100005],ed[100005],tot=0,ans=0,dep[100005],nw[100005];
vector<ll> s[100005],ty[100005],x[100005],x2[100005];
bool cmp(ll a,ll b){return dfn[a]<dfn[b];}
void dfs(int p,int f)
{
	ll i,v;
	ed[p]=dfn[p]=++tot;
	dep[p]=dep[f]+1;
	for(i=0;i<s[p].size();i++)
	{
		v=s[p][i];
		if(v==f)continue;
		dfs(v,p);
		ed[p]=ed[v];
	}
}
void upd(int p,int l,int r)
{
	tr[p].sum=0;
	if(tr[p].cnt)tr[p].sum=r-l+1;
	else if(l!=r)tr[p].sum=tr[2*p].sum+tr[2*p+1].sum;
}
void add(int p,int l,int r,int gl,int gr,int v)
{
	int mid;
	if(gl>gr)return;
	if(l>gr||r<gl)return;
	if(l>=gl&&r<=gr)
	{
		tr[p].cnt+=v;
		upd(p,l,r);
		return;
	}
	mid=(l+r)/2;
	add(2*p,l,mid,gl,gr,v);
	add(2*p+1,mid+1,r,gl,gr,v);
	upd(p,l,r);
}
void dfs2(int p,int f)
{
	ll i,j,w,r,hd=0,pre=0;
	nw[dep[p]]=p;
	sort(x2[p].begin(),x2[p].end(),cmp);
	for(i=0;i<x[p].size();i++)
	{
		r=x[p][i];
		add(1,1,n,dfn[r],ed[r],1);
	}
	for(i=0;i<ty[p].size();i++)
	{
		r=nw[ty[p][i]];
		add(1,1,n,1,dfn[r]-1,1);
		add(1,1,n,ed[r]+1,n,1);
	}
	ans+=n-tr[1].sum;
	for(i=0;i<s[p].size();i++)
	{
		w=s[p][i];
		if(w==f)continue;
		while(hd<x2[p].size()&&dfn[x2[p][hd]]>=dfn[w]&&dfn[x2[p][hd]]<=ed[w])
		{
			add(1,1,n,dfn[x2[p][hd]],ed[x2[p][hd]],-1);
			hd++;
		}
		dfs2(w,p);
		for(j=pre;j<hd;j++)
		{
			r=x2[p][j];
			add(1,1,n,dfn[r],ed[r],1);
		}
		pre=hd;
	}
	for(i=0;i<x[p].size();i++)
	{
		r=x[p][i];
		add(1,1,n,dfn[r],ed[r],-1);
	}
	for(i=0;i<ty[p].size();i++)
	{
		r=nw[ty[p][i]];
		add(1,1,n,1,dfn[r]-1,-1);
		add(1,1,n,ed[r]+1,n,-1);
	}
}
int main()
{
	scanf("%lld%lld",&n,&m);
	for(i=1;i<n;i++)
	{
		scanf("%lld%lld",&u,&v);
		s[u].push_back(v);
		s[v].push_back(u);
	}
	dfs(1,0);
	for(i=1;i<=m;i++)
	{
		scanf("%lld%lld",&u,&v);
		if(dfn[u]>dfn[v])swap(u,v);
		if(dfn[v]>=dfn[u]&&dfn[v]<=ed[u])
		{
			ty[v].push_back(dep[u]+1);
			x2[u].push_back(v);
			add(1,1,n,dfn[v],ed[v],1);
		}
		else
		{
			x[u].push_back(v);
			x[v].push_back(u);
		}
	}
	dfs2(1,0);
	printf("%lld\n",(ans-n)/2LL);
	return 0;
 } 

上一题