【宝藏】题解(五校联考3day1)
分析
如果打爆搜的话可以拿60分。
首先知道期望是可以累加的,即i通过j去到k的期望,等于i去到j的期望加j去到k的期望。
所以令d[i]表示i的出度,F[i]表示从i到i的父亲的期望,G[i]表示i的父亲到i的期望,j表示i其中任意一个儿子,k表示i的父亲,l表示k其中任意一个儿子,e表示k的父亲。
很容易推出:
\]
\]
简化后得
\]
\]
然后分q次走,用倍增lca很容易算出vi到vi+1的期望,把期望累加就可以了。
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int d[600000],g[600000],f[600000],last[600000],next[600000],a[600000],dad[60000][50],deep[600000],fsum[600000],gsum[600000],m2[100];
int n,m,test,q,p,tot;
int bj(int x,int y)
{
	next[++tot]=last[x];
	last[x]=tot;
	a[tot]=y;
	d[x]++;
}
int dg(int x,int fa)
{
	deep[x]=deep[fa]+1;
	f[x]+=d[x];
	for(int i=last[x];i;i=next[i])
	{
		if(a[i]!=fa)
		{
			dg(a[i],x);
			f[x]+=f[a[i]];
		}
	}
}
int dg1(int x,int fa)
{
	int allj=0;
	for(int i=last[x];i;i=next[i])
	{
		if(a[i]!=fa)
		{
			allj+=f[a[i]];
		}
	}
	for(int i=last[x];i;i=next[i])
	{
		if(a[i]!=fa)
		{
			g[a[i]]=d[x]+g[x]+allj-f[a[i]];
		}
	}
	for(int i=last[x];i;i=next[i])
	{
		if(a[i]!=fa)
		{
			dg1(a[i],x);
		}
	}
}
int dg2(int x,int fa)
{
	dad[x][0]=fa;
	fsum[x]=fsum[fa]+f[x];
	gsum[x]=gsum[fa]+g[x];
	for(int i=last[x];i;i=next[i])
	{
		if(a[i]!=fa)
			dg2(a[i],x);
	}
}
int work(int x,int y,int z)
{
	return fsum[x]-fsum[z]+gsum[y]-gsum[z];
}
int lca(int x,int y)
{
	if(x==y) return 0;
	int l=0;
	if(deep[x]<deep[y])
	{
		l=x;
		x=y;
		y=l;
		l=10000000;
	}
	int i,xx=x,yy=y,j;
	if(deep[xx]>deep[yy])
	{
		j=int(log2(deep[xx]));
		for(i=j;i>=0;i--)
		{
			if(deep[dad[xx][i]]>deep[yy])
			{
				xx=dad[xx][i];
			}
		}
		xx=dad[xx][0];
	}
	if(xx==yy)
	{
		if(l==0) return work(x,y,xx);
		else return work(y,x,xx);
	}
	j=int(log2(deep[xx]));
    for(i=j;i>=0;i--)
	{
        if (dad[xx][i]!=dad[yy][i])
		{
            xx=dad[xx][i];
            yy=dad[yy][i];
        }
    }
    xx=dad[xx][0];
    if(l==0) return work(x,y,xx);
		else return work(y,x,xx);
}
int main()
{
	int i,j,k,l,x,y;
	m2[0]=1;
	for(i=1;i<=20;i++)
		m2[i]=m2[i-1]*2;
	scanf("%d",&test);
	while(test--)
	{
		scanf("%d",&n);
		tot=0;
		memset(d,0,sizeof(d));
		memset(g,0,sizeof(g));
		memset(f,0,sizeof(f));
		memset(a,0,sizeof(a));
		memset(last,0,sizeof(last));
		memset(next,0,sizeof(next));
		memset(dad,0,sizeof(dad));
		memset(deep,0,sizeof(deep));
		memset(fsum,0,sizeof(fsum));
		memset(gsum,0,sizeof(gsum));
		for(i=1;i<=n-1;i++)
		{
			scanf("%d%d",&x,&y);
			bj(x,y);
			bj(y,x);
		}
		deep[0]=0;
		dg(0,0);
		dg1(0,0);
		dg2(0,0);
		for(j=1;j<=int(log2(n));j++)
		{
			for(i=1;i<=n;i++)
			{
				dad[i][j]=dad[dad[i][j-1]][j-1];
			}
		}
		scanf("%d",&q);
		for(i=1;i<=q;i++)
		{
			int ans=0;
			scanf("%d%d",&p,&x);
			for(j=1;j<=p;j++)
			{
				scanf("%d",&y);
				ans+=lca(x,y);
				x=y;
			}
			printf("%d.0000\n",ans);
		}
		cout<<endl;
	}
}
【宝藏】题解(五校联考3day1)的更多相关文章
- 【五校联考1day2】JZOJ2020年8月12日提高组T2 我想大声告诉你
		[五校联考1day2]JZOJ2020年8月12日提高组T2 我想大声告诉你 题目 Description 因为小Y 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一 ... 
- 【五校联考1day2】JZOJ2020年8月12日提高组T1 对你的爱深不见底
		[五校联考1day2]JZOJ2020年8月12日提高组T1 对你的爱深不见底 题目 Description 出乎意料的是,幸运E 的小R 居然赢了那个游戏.现在欣喜万分的小R 想要写一张明信片给小Y ... 
- 【C】题解 (五校联考3day2)
		分析 这道题看上去很恶心,实际上只用记录四坨东西就能打DP了:y坐标最小的向上射的点.y坐标最大的向下射的点.y坐标最大和最小的向右射的点,转移显然.注意,如果该状态的值为零就可以略过,否则会超时. ... 
- NOIP2016提高A组五校联考3总结
		第一题,本来一开始就想到了数位dp,结果脑残地打了十几个转移方程,总是调试不出来,一气之下放弃了. 调第一题几乎调了整节比赛,第二第三都没它. 第二题连边找联通块. 第三题题解都打了三页,看都不想看. ... 
- 【五校联考5day1】登山
		题目 描述 题目大意 给你一个n∗nn*nn∗n的网格图.从(0,0)(0,0)(0,0)开始,每次只可以向右或向上移动一格,并且不能越过对角线(即不能为x<yx<yx<y). 网格 ... 
- 【2020五校联考NOIP #2】矩阵
		咕咕咕到现在~ 题面传送门 题意: 给出一个 \(n\times n\) 的矩阵 \(A\).要你求有多少个 \(n\times n\) 的矩阵 \(B\) 满足: 每一行都是 \(1\) 到 \(n ... 
- 五校联考 running (欧拉函数)
		题面 \(solution:\) 讲真吧,这道题真的出得,嗯,太恐怖了.考场上这道题真的把我看懵了,这道题以前是见过的,但欧拉函数?我学过吗?一道容斥都要超时的题目,我都要为我自己点根香了,拿着gcd ... 
- 【五校联考3day2】C
		題意: 現有一平面直角坐標系,有n個點,每一個點必須向某一個方向發射射線,且任意一條射線必須與某一條坐標軸平行.定義一種發射射線的方案是合法的,則方案必須滿足: 1.沒有一條射線交叉 2.沒有一條射線 ... 
- 五校联考R1 Day1T3 平面图planar(递推 矩阵快速幂)
		题目链接 我们可以把棱柱拆成有\(n\)条高的矩形,尝试递推. 在计算的过程中,第\(i\)列(\(i\neq n\))只与\(i-1\)列有关,称\(i-1\)列的上面/下面为左上/左下,第\(i\ ... 
随机推荐
- jest 事件测试
			概述 最近玩 Jest,测试 Vue 组件上的事件,有一些心得,记录下来供以后开发时参考,相信对其他人也有用. 事件测试 对于 Vue 组件上的事件,分为 2 种,一种是子组件 Emit 的事件,另一 ... 
- Group by的用法
			Group by的用法 GROUP BY 语句根据一个或多个列对结果集进行分组.在分组的列上我们可以使用 COUNT, SUM, AVG,等函数. Group by用法: SELECT column_ ... 
- JVM监控工具之JVisualVM
			一.简介 JVisualVM是Netbeans的profile子项目,已在JDK6.0 update 7 中自带(bin/jvisualvm.exe),能够监控线程,内存情况,查看方法的CPU时间和内 ... 
- 【Linux 应用编程】进程管理 - 进程间通信IPC之管道 pipe 和 FIFO
			IPC(InterProcess Communication,进程间通信)是进程中的重要概念.Linux 进程之间常用的通信方式有: 文件:简单,低效,需要代码控制同步 管道:使用简单,默认阻塞 匿名 ... 
- LeetCode链表简单题
			一.21合并两个有序链表 代码如下: class Solution: def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNod ... 
- 【Linux开发】Linux启动脚本设置
			前言linux有自己一套完整的启动 体系,抓住了linux启动 的脉络,linux的启动 过程将不再神秘.阅读之前建议先看一下附图.本文中假设inittab中设置的init tree为:/etc/rc ... 
- TestNG+extentReports+log4j2 完善自动化测试框架——美观的报告和保留日志文件
			1:导入Maven依赖<dependency> <groupId>com.aventstack</groupId> <artifactId>extent ... 
- [转帖]Oracle 查询各表空间使用情况--完善篇
			Oracle 查询各表空间使用情况--完善篇 链接:http://blog.itpub.net/28602568/viewspace-1770577/ 标题: Oracle 查询各表空间使用情况--完 ... 
- JavaScript的二维数组
			二维数组的初始化: 实例① var arr = [[1,2],['a','b']]; console.log(arr[1][0]); //a 第2列第1行所在的元素 实例② var arr = new ... 
- Python 入门之编码
			Python 入门之编码 1.编码初识: (1)ASCII码 :256 个 英文1个字节,不支持中文 (2)GBK(国标) : 英文1个字节 中文两个字节 (3)unicode (万国码):英文4个字 ... 
