6546. 【GDOI2020模拟4.8】USACO 2020 Open Contest, Platinum(circus)

题目描述

Farmer John 马戏团的 N 头奶牛( 1 ≤ N ≤ 10^5 )正在准备她们接下来的演出。演出在一棵结点编号为 1 … N 的树上进行。演出的“起始状态”可以定义为一个整数 1 ≤ K ≤ N 以及奶牛 1 … K 在树上的结点分布,使得没有两头奶牛位于相同的结点。 在一场演出中,奶牛们可以进行任意次数的“移动”。在一次移动中,一头奶牛从她的当前所在结点移动到一个未被占据的相邻结点。称两个起始状态是等价的,如果一个状态可以通过一系列移动到达另一个。

对于每一个 1 ≤ K ≤ N ,帮助奶牛们求出起始状态的等价类数量:即可选出的起始状态的最大数量,使得两两不等价。由于这些数字可能很大,输出模 10^9 + 7 的余数。

N ≤ 10^5

题解

很神奇的题目

猜结论,k只奶牛的位置不影响结果,最大数量只与奶牛间是否能交换有关,若干奶牛可以交换则只算一次

证明不会

所以可以假设k只奶牛都是当前深度最大的,只需要维护是否能交换即可,视作边

选一个度数>=3的点做根,如果没有就是链

关系有根与根之间的,父子间的以及兄弟(父亲不是根节点)间的,其余的关系可通过这三种得到

设编号从下往上从小到大,显然k=n-1和n时答案为k!

当k=n-2时,除编号为n-1的儿子以外,其余的根均相连

k<=n-3时所有根相连

当k<=n-2时兄弟相连

对于每个点x设dis[x]表示x向上到某个度数>=3的点的距离,因为根节点的度数>=3所以必然存在

所以x与儿子相连的条件是dis[x]+2<=n-k,即把向上的一段移开并多出两个来交换

只可能向上,因为如果要在一个非根节点处向另一棵子树走的话,父亲边+走上来的边+走下去的边已经有至少三条了

对于每种情况在考虑一下两端的出现时间,以及根的话要考虑父亲的出现时间,可以建一个0点来连

最后变成若干条边,每条边有出现时间,求每个时间的连通情况,线段树分治+可撤销并查集即可

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define mod 1000000007
#define Mod 1000000005
#define ll long long
#define file
using namespace std;

struct type{int x,y,X,Y,s;} b[300001],S;
int a[200001][2],ls[100001],D[100001],d[100001],num[100001],dis[100001],size[100001];
int fa[100001],dp[100001],n,i,j,k,l,root,len,h,t,tot;
ll jc[100001],Jc[100001],w[100001],ans;
vector<int> tr[400001];
bool bz[100001];

ll qpower(ll a,int b) {ll ans=1;while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
void New(int x,int y) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;}

void bfs()
{
	int i,j,k,l;

	h=0;t=1;d[1]=root;
	while (h<t)
	{
		bz[d[++h]]=1;num[d[h]]=n-h+1;
		for (i=ls[d[h]]; i; i=a[i][1])
		if (!bz[a[i][0]])
		{
			bz[a[i][0]]=1;
			d[++t]=a[i][0];
		}
	}
}

void change(int t,int l,int r,int x,int y,int s)
{
	int mid=(l+r)/2;
	if (x<=l && r<=y) {tr[t].push_back(s);return;}

	if (x<=mid) change(t*2,l,mid,x,y,s);
	if (mid<y) change(t*2+1,mid+1,r,x,y,s);
}

void add(int x,int y,type s) {if (x<=y) b[++tot]={s.x,s.y,0},change(1,1,n,x,y,tot);}

void dfs(int Fa,int t,int Dis)
{
	int i,Ls=0;
	dis[t]=Dis;

	if (dis[Fa]) add(num[Fa],n-dis[Fa]-2,{t,Fa,0});
	if (num[Fa]==n-1) add(num[t],min(num[Fa]-1,n-3),{0,t,0}); else add(num[t],min(num[Fa]-1,n-2),{0,t,0});

	for (i=ls[t]; i; i=a[i][1])
	if (a[i][0]!=Fa)
	{
		dfs(t,a[i][0],(D[t]<=2)?Dis+1:1);
		if (Fa)
		{
			if (Ls) add(num[Ls],n-2,{Ls,a[i][0],0});
			Ls=a[i][0];
		}
	}
}

int gf(int t) {if (fa[t]==t) return t;return gf(fa[t]);}
void swap(int &x,int &y) {int z=x;x=y;y=z;}
void link(int id)
{
	int x=b[id].x,y=b[id].y,X=gf(x),Y=gf(y);
	if (X==Y) {b[id].X=-1; return;}

	if (dp[X]>dp[Y]) swap(X,Y);
	fa[X]=Y;
	if (dp[X]<dp[Y]) b[id].s=0; else b[id].s=1,++dp[Y];

	ans=ans*jc[size[X]]%mod*jc[size[Y]]%mod*Jc[size[X]+size[Y]]%mod;
	size[Y]+=size[X];
	b[id].X=X,b[id].Y=Y;
}
void cut(int id)
{
	int X=b[id].X,Y=b[id].Y;
	if (X==-1) return;

	fa[X]=X;dp[Y]-=b[id].s;
	ans=ans*jc[size[Y]]%mod*Jc[size[X]]%mod*Jc[size[Y]-size[X]]%mod;
	size[Y]-=size[X];
}

void work(int t,int l,int r)
{
	int N=tr[t].size(),i,mid=(l+r)/2;

	if (l==r && l==3)
	n=n;

	fo(i,0,N-1)
	link(tr[t][i]);
	if (l==r)
	{
		printf("%lld\n",ans*jc[l]%mod);
		fd(i,N-1,0) cut(tr[t][i]);
		return;
	}

	work(t*2,l,mid);
	work(t*2+1,mid+1,r);

	fd(i,N-1,0) cut(tr[t][i]);
}

int main()
{
	freopen("circus.in","r",stdin);
	#ifdef file
	freopen("circus.out","w",stdout);
	#endif

	scanf("%d",&n);
	jc[0]=jc[1]=Jc[0]=Jc[1]=w[1]=1;
	fo(i,2,n) w[i]=mod-w[mod%i]*(mod/i)%mod,jc[i]=jc[i-1]*i%mod,Jc[i]=Jc[i-1]*w[i]%mod,scanf("%d%d",&j,&k),New(j,k),New(k,j),++D[j],++D[k];
	fo(i,1,n) fa[i]=i,size[i]=dp[i]=1;fa[0]=0;dp[0]=1;
	fo(i,1,n) if (D[i]>2) {root=i;break;}

	if (!root) {fo(i,1,n) printf("%lld\n",jc[i]);return 0;}

	bfs();
	dfs(0,root,0);
	ans=1;
	work(1,1,n);

	fclose(stdin);
	fclose(stdout);

	return 0;
}

原文地址:https://www.cnblogs.com/gmh77/p/12685446.html

时间: 2024-11-08 05:45:31

6546. 【GDOI2020模拟4.8】USACO 2020 Open Contest, Platinum(circus)的相关文章

USACO 2018 December Contest Platinum T2: Sort It Out

题目大意 FJ有 N(1≤N≤1e5 )头奶牛(分别用 1…N 编号)排成一行.FJ喜欢他的奶牛以升序排列,不幸的是现在她们的顺序被打乱了.在过去FJ曾经使用一些诸如“冒泡排序”的开创性的算法来使他的奶牛排好序,但今天他想偷个懒.取而代之,他会每次对着一头奶牛叫道“按顺序排好”.当一头奶牛被叫到的时候,她会确保自己在队伍中的顺序是正确的(从她的角度看来).当有一头紧接在她右边的奶牛的编号比她小,她们就交换位置.然后,当有一头紧接在她左边的奶牛的编号比她大,她们就交换位置.这样这头奶牛就完成了“按

USACO 2019 January Contest Platinum T3: Train Tracking 2

题目大意 每天特快列车都会经过农场.列车有N节车厢(1≤N≤10^5),每节车厢上有一个1到10^9之间的正整数编号:不同的车厢可能会有相同的编号. 平时,Bessie会观察驶过的列车,记录车厢的编号.但是今天雾实在太浓了,Bessie一个编号也看不见!幸运的是,她从城市里某个可靠的信息源获知了列车编号序列的所有滑动窗口中的最小值.具体地说,她得到了一个正整数K,以及N−K+1个正整数c1,…,cN+1−K,其中ci是车厢i,i+1,…,i+K−1之中编号的最小值. 帮助Bessie求出满足所有

USACO 2019 February Contest Platinum T1: Cow Dating

题目大意 由于目前可供奶牛们使用的约会网站并没有给Farmer John留下深刻印象,他决定推出一个基于新匹配算法的奶牛交友网站,该算法可基于公牛和母牛间的共同兴趣对公牛和母牛进行匹配. Bessie在寻找情人节Barn Dance的合作伙伴时,决定试用这个网站.在注册账户之后,FJ的算法为他给出了一个长度为 N(1≤N≤1e6) 的匹配列表,列表上每头公牛接受她舞蹈邀请的概率为 p (0 < p < 1). Bessie决定向列表中的一个连续区间内的奶牛发送邀请,但Bessie希望恰好只有一

USACO 2017 December Contest Platinum T2: Push a Box

题目大意 一个谷仓是一个N*M的矩形网格,有一些网格里有干草.Bessie站在其中一个格子内,还有一个格子里有一个大木箱.Bessie不能和大木箱在一个格子里,也不能和干草在一个格子里. 如果她不与干草一个格子,她就可以往自己旁边的四个方向(东西南北)移动,如果她想移动到有木箱的格子里,那个木箱就会被她推一格(只要木箱的那个方向还有空间),如果没有空间,那Bessie就不能移动了. 给你谷仓的布局(空格子,干草以及木箱位置)以及Bessie的出发位置和箱子要被推到的位置,请你帮忙计算Bessie

USACO 2017 December Contest Platinum T3: Greedy Gift Takers

题目大意 有 N(1≤N≤1e5)头牛按顺序排成一列,编号从 1 到 N,1 号牛在队头,N 号牛在队尾. 每次位于队头的牛 i 拿到一个礼物,然后插入到从队尾数ci?头牛之前的位置..举个栗子: 初始队列 1,2,3,4,5 c1?= 2,c2? = 3,则第一次操作后的序列为 2,3,1,4,5,第二次操作后的序列为 3,2,1,4,5.重复无限次操作,求最后有几头牛拿不到礼物. 题目分析 一上来有个显然的结论,若一个人得不到礼物那么原序列中在他后面的人肯定也得不到礼物,因为后面的人跳不到前

题解 loj3265 3266 3267 USACO 2020.2 Platinum(全)

loj3265 「USACO 2020.2 Platinum」Delegation 因为是最大化最小值,考虑二分答案. 设当前二分的答案为\(K\).则要判断是否有一种划分方式,使得每条链的长度都至少为\(K\). 不妨以\(1\)为根,对整棵树dfs.记\(fa(u)\)为\(u\)的父亲节点.dfs(u)函数求出一个值\(f(u)\),或判断在当前的\(K\)下无解.有解时,我们把\(u\)的子树划分为若干条长度\(\geq K\)的链,并选择一条未完结的链(允许这条链长度\(<K\))覆盖

6442. 【GDOI2020模拟01.18】钩子

题目描述 Description Input Output Sample Input Sample Input1 3 1000000007 Sample Input2 4 1000000007 Sample Output Sample Output1 0 1 0 500000004 0 500000004 500000004 0 500000004 Sample Output2 0 500000004 500000004 0 333333336 166666668 166666668 33333

[题解]某模拟题(USACO月赛部分题+noip2005部分题)

题目描述 农场上有N(1 <= N <= 50,000)堆草,放在不同的地点上.FJ有一辆拖拉机,也在农场上.拖拉机和草堆都表示为二维平面上的整数坐标,坐标值在1..1000的范围内.拖拉机的初始位置与所有草堆不同. FJ开拖拉机时,只能平行于坐标轴(即东.南.西.北四个方向),而且每次开动的一段必须是整数长度.例如,他可以向北开2个单位长度,然后向东开3个单位长度.拖拉机不能开到草堆的位置. 请帮助FJ计算出最少要移动多少个草堆,他才能将拖拉机开回坐标原点. 拖拉机可以开到1..1000之外

【GDOI2020模拟01.16】划愤(nim积+行列式)

https://gmoj.net/senior/#contest/show/2989/1 先考虑n=2时怎么做,打表找规律找了半天找不出来. 赛后才知道这是nim积. 定义\(x?y\)为\(sg(x,y)\). 有一坨性质: \(x,y<2^{2^k},x?y<2^{2^k}\) \(2^{2^k}?2^{2^k}={3 \over 2}2^{2^k}\) 可以把?看做乘法,\(⊕\)(异或)看做加法,所以还有分配律. 求\(x?y(x>y)\),设\(k\)为最大的\(k\)满足\(