首页 > 其他分享 >BSOJ7020题解

BSOJ7020题解

时间:2022-08-17 16:13:50浏览次数:43  
标签:const int 题解 times BSOJ7020 return data mod

脑抽了。考场上应该做掉这题的。

所以实际挂分从100pts变成了200pts/fn/fn/fn

考虑用一个二元组来维护链,\((f,g)\) 表示这个集合的所有链的点权和为 \(f\),有 \(g\) 条链,目的是方便转移。

定义两个二元组 \(x,y\) 的二元运算:\(x+y\) 表示合并两个集合,\(x\times y\) 表示将两个集合中选择两条链拼接起来之后的链集合,对于常数 \(c\),\(x\times c\) 表示给所有链的权值都加上一个 \(c\),\(f[u]\) 表示答案集合。

给每个边加一个点权 \(w[u]=[V[u]<V[f[u]]]\)(大于号和小于号没区别),于是问题就变成了边权交错。

设 \(f0[u],f1[u]\) 表示 \(u\) 到子树内的链中,\(u\) 的儿子节点权值是 \(0/1\) 的链集合。(用上述二元组维护)

合并答案的话,因为另一条链要被反过来,所以实际上对于点对 \((u,v)\)(\(u,v\) 父亲相同)实际上要求的应该是 \(w[u]=w[v]\)。但是需要加上一个链 \((u,v)\),所以实际上是:

\[f1[u]=f1[u]+(f0[v]\times V[v]+(V[u]+V[v],1)) \]

\(f0\) 同理。

对于 \(f\) 的转移,显然就是 \(f[u]=f[u]+f[v]+(w[v]?(f0[v]\times V[v])\times f1[u]:(f1[v]\times V[v])\times f0[u])\)。

接下来考虑换根。

首先对于 \(u\),先把所有与其连接的节点按照上述方式转移。

然后,对于一个儿子,应该将其对自身的贡献去掉。容易发现上述转移是存在逆操作的,只需要定义两个集合之间的减法即可。

然后。。。随便转移就完了。。。。。。甚至没有细节。。。。。。

#include<cstdio>
#include<cctype>
typedef long long ll;
const int M=1e5+5;
int n,q,mod,ege,w[M],V[M],h[M];int f[M],d[M],son[M],siz[M],top[M];
struct data{
	int f,g;
	data(const int&f=0,const int&g=0):f(f),g(g){}
	inline data operator+(const data&it)const{
		return data((f+it.f)%mod,(g+it.g)%mod);
	}
	inline data operator-(const data&it)const{
		return data((mod+f-it.f)%mod,(mod+g-it.g)%mod);
	}
	inline data operator*(const data&it)const{
		return data((1ll*f*it.g+1ll*g*it.f)%mod,1ll*g*it.g%mod);
	}
	inline data operator+(const int&it)const{
		return data((f+it)%mod,g+1);
	}
	inline data operator*(const int&it)const{
		return data((f+1ll*g*it)%mod,g);
	}
}F0[M],F1[M],G0[M],G1[M],F[M],G[M];
struct Edge{
	int v,nx;
}e[M<<1];
inline void Add(const int&u,const int&v){
	e[++ege]=(Edge){v,h[u]};h[u]=ege;
	e[++ege]=(Edge){u,h[v]};h[v]=ege;
}
inline void DFS1(const int&u){
	siz[u]=1;d[u]=d[f[u]]+1;
	for(int v,E=h[u];E;E=e[E].nx)if((v=e[E].v)^f[u])f[v]=u,DFS1(v),siz[u]+=siz[v],siz[v]>siz[son[u]]&&(son[u]=v);
}
inline void DFS2(const int&u,const int&tp){
	top[u]=tp;if(!son[u])return;DFS2(son[u],tp);
	for(int E=h[u];E;E=e[E].nx)if(e[E].v^f[u]&&e[E].v^son[u])DFS2(e[E].v,e[E].v);
}
inline int Find(int u,const int&v){
	while(top[u]^top[v]){
		if(f[top[u]]==v)return top[u];u=f[top[u]];if(!u)return-1;
	}
	return d[u]<d[v]?-1:son[v];
}
inline void DP1(const int&u){
	F0[u]=F1[u]=F[u]=data();
	for(int v,E=h[u];E;E=e[E].nx)if((v=e[E].v)^f[u]){
		DP1(v);F[u]=F[u]+(F[v]+(w[v]?F1[u]*(F0[v]+V[v]):F0[u]*(F1[v]+V[v])));
		if(w[v])F1[u]=F1[u]+(F0[v]*V[u]+(V[u]+V[v]));else F0[u]=F0[u]+(F1[v]*V[u]+(V[u]+V[v]));
	}
	F[u]=F[u]+F0[u]+F1[u];
}
inline void DP2(const int&u){
	data f0,f1,sum;G[u]=G[u]+G0[u]+G1[u];
	for(int v,E=h[u];E;E=e[E].nx){
		if((v=e[E].v)==f[u]){
			const int&W=w[u]^1;
			sum=sum+(G[u]+(W?f1*(G0[u]+V[v]):f0*(G1[u]+V[v])));
			if(W)f1=f1+(G0[u]*V[u]+(V[u]+V[v]));else f0=f0+(G1[u]*V[u]+(V[u]+V[v]));
		}
		else{
			const int&W=w[v];
			sum=sum+(F[v]+(W?f1*(F0[v]+V[v]):f0*(F1[v]+V[v])));
			if(W)f1=f1+(F0[v]*V[u]+(V[u]+V[v]));else f0=f0+(F1[v]*V[u]+(V[u]+V[v]));
		}
	}
	for(int v,E=h[u];E;E=e[E].nx)if((v=e[E].v)^f[u]){
		const int&W=w[v];
		if(W)f1=f1-(F0[v]*V[u]+(V[u]+V[v]));else f0=f0-(F1[v]*V[u]+(V[u]+V[v]));
		sum=sum-(F[v]+(W?f1*(F0[v]+V[v]):f0*(F1[v]+V[v])));
		G[v]=sum;G0[v]=f0;G1[v]=f1;DP2(v);
		sum=sum+(F[v]+(W?f1*(F0[v]+V[v]):f0*(F1[v]+V[v])));
		if(W)f1=f1+(F0[v]*V[u]+(V[u]+V[v]));else f0=f0+(F1[v]*V[u]+(V[u]+V[v]));
	}
}
inline int read(){
	int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
inline void write(int n){
	static char s[15];int top(0);while(s[++top]=n%10^48,n/=10);while(putchar(s[top]),--top);putchar(10);
}
signed main(){
	int r,s;n=read();mod=read();
	for(int i=1;i<=n;++i)V[i]=read();for(int u,v,i=1;i<n;++i)u=read(),v=read(),Add(u,v);
	DFS1(1);DFS2(1,1);for(int i=2;i<=n;++i)w[i]=V[f[i]]>V[i];DP1(1);DP2(1);q=read();
	while(q--){
		int x;r=read();s=read();x=Find(r,s);
		if(s==r)write(F[1].f);else if(!~x)write(F[s].f);else write(G[x].f);
	}
}

标签:const,int,题解,times,BSOJ7020,return,data,mod
From: https://www.cnblogs.com/lmpp/p/16595568.html

相关文章

  • 针对“RuntimeError: each element in list of batch should be of equal size” 问题
    第一次运行代码出现了这个问题:这个问题的出现主要来源于DataLoader类中的collate.py文件造成的问题,由于每个batch里的长度不一致,因此导致出现了该问题。通过百度方法和......
  • 「AGC012F」Prefix Median 题解 (DP)
    题目简介给定一个长度为\(2n-1\)的序列\(a\),你可以随意排列\(a\)中的元素,请求出有多少种不同的序列\(b\),满足\(b\)的长度为\(n\)。\(b_i=\{a_1\ldotsa_{2......
  • 洛谷P1972HH的项链 题解
    P1972[SDOI2009]HH的项链题目描述HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含......
  • LeetCode 螺旋矩阵 II 算法题解 All In One
    LeetCode螺旋矩阵II算法题解AllInOnejs/ts生成螺旋矩阵螺旋矩阵原理图解动态赋值arr[i]//动态更新indexleti=0;while(left<=right&&t......
  • ARC094D题解
    设\(A<B\),\(C=\max(\sqrt{AB-1},A)\),答案为:\[C-1+\frac{AB-1}{C+1}\]如果\(A>B\)时显然可以互换,接下来称\(A\)所在的比赛为第一场比赛,\(B\)所在的比赛为第二场比赛......
  • 题解 [ZJOI2010]排列计数
    好题。%你赛考到了不会摆烂,后来发现原来有向下取整,题面没有。。。(就算有我也做不出来啦qAq首先我们会发现这个长得就是小根堆,答案就变成了小根堆的计数。首先最小的......
  • ubuntu16.04中文乱码问题解决
    1、先输入locale-a,查看一下现在已安装的语言2、若不存在如zh_CN之类的语言包,进行中文语言包装:apt-getinstalllanguage-pack-zh-hans3、安装好后我们可以进行临时修......
  • LeetCode 反转链表算法题解 All In One
    LeetCode反转链表算法题解AllInOnejs/ts实现反转链表反转链表原理图解双指针,swap交换//反转双指针//swap:a=b;c=a;b=c;letprev:List......
  • 洛谷P1714切蛋糕题解
    P1714切蛋糕题目描述今天是小Z的生日,同学们为他带来了一块蛋糕。这块蛋糕是一个长方体,被用不同色彩分成了\(n\)个相同的小块,每小块都有对应的幸运值。小Z作......
  • 【题解】【Shopping】【树上依赖型背包】
    很厉害的题。在任务计划里躺了一年。。。题目传送门思考之路题目要让我们在付出不超过m的代价在树上找到一个权值最大的连通块。容易想到树形dp,设\(f_{i,j}\)表示选的......