首页 > 其他分享 >题解 [NOI2020] 命运

题解 [NOI2020] 命运

时间:2023-08-01 12:11:22浏览次数:59  
标签:return 命运 NOI2020 int 题解 sum dep cdots rc

Link

题意

给定一棵 \(n\) 个节点的有根树和 \(m\) 条祖先到后代的链。问有多少种把边权设置为 \(0\) 或 \(1\) 的方案使得每条链上至少有一条边是 \(1\)。

答案对 \(998244353\) 取模。

\(1 \leq n,m \leq 5 \times 10^5\)

题解

我们将链的下端称为限制的起点。容易发现,对于同一个起点,终点越深,限制越强,于是不妨只考虑起点。

设 \(f(u,x)\) 表示限制的起点在 \(u\) 的子树之内,不满足条件的限制最深深度为 \(x\) 的方案数。最终显然有 \(f(1,0)\) 为答案。

考虑树形 DP,不断合并子树来求解 \(f\)。首先遍历 \(u\) 为起点的限制,求出最深的深度 \(d_{max}\),则初始子树中只有 \(u\) 一个点,\(f(u,d_{max})=1\)。

考虑合并子树 \(v\),根据 \((u,v)\) 这条边是 \(0\) 还是 \(1\) 转移:

\[f(u,d) \leftarrow \sum \limits_{i=0}^{d} f(v,i) f(u,d) +\sum \limits_{i=0}^{d-1}f(u,i)f(v,d) + \sum \limits_{i=0}^{dep_u} f(v,i)f(u,d) \]

考虑第二个和式的上界是 \(d-1\),因为 \(f(u,d)f(v,d)\) 会出现两次。

记前缀和 \(g(u,d) = \sum \limits_{i=0}^d f(u,d)\),

\[f(u,d) \leftarrow g(v,d)f(u,d)+g(u,d-1)f(v,d)+g(v,dep_u)f(u,d) \\ f(u,d) \leftarrow f(u,d)(g(v,d)+g(v,dep_u))+g(u,d-1)f(v,d) \]

考虑线段树合并转移。这里讲一下转移过程:\(g(v,dep_u)\) 在整个合并过程中都是常量,可以提前查询得到。合并到 \([l,r]\) 时维护 \(g(u,l-1)\) 和 \(g(v,l-1)\),因为我们是从左到右合并,于是这是容易维护的。

如果 \(u,v\) 的树上都有 \([l,r]\) 的节点,直接递归合并。到叶子了就按照上面的式子直接转移。重点讲一下 \(u,v\) 有一个为空的情况:

  • \(u\) 为空,那么 \(f(u,l\cdots r)=0\),于是上面式子里面 \(f(u,d)\) 的项全是 \(0\),且区间内的 \(g(u,d-1) = g(u,l-1)\)。直接给 \(f(v,l\cdots r)\) 乘上 \(g(u,l-1)\) 即可。
  • \(v\) 为空,那么 \(f(v,l\cdots r) =0\),于是上面式子里面 \(f(v,d)\) 的项全是 \(0\),且区间内的 \(g(v,d) = g(v,l-1)\)。直接给 \(f(u,l\cdots r)\) 乘上 \(g(v,l-1)+g(v,dep_u)\) 即可。
# include <bits/stdc++.h>

const int N=500010,mod=998244353;

int n,m;

int dep[N],rt[N];

std::vector <int> G[N];
std::vector <int> lim[N]; 

struct Node{
	int sum,lc,rc,tag;
	Node(){
		tag=1;
		return;
	}
}tr[N*30];
int cnt;



inline int read(void){
	int res,f=1;
	char c;
	while((c=getchar())<'0'||c>'9')
		if(c=='-') f=-1;
	res=c-48;
	while((c=getchar())>='0'&&c<='9')
		res=res*10+c-48;
	return res*f;
}

inline void add(int &x,int v){
	x+=v;
	if(x>=mod) x-=mod;
	return;
}
inline int adc(int a,int b){
	return (a+b<mod)?(a+b):(a+b-mod); 
}
inline int mul(int a,int b){
	return 1ll*a*b%mod;
}
inline int& lc(int x){
	return tr[x].lc;
}
inline int& rc(int x){
	return tr[x].rc;
}

inline void pushup(int x){
	tr[x].sum=adc(tr[lc(x)].sum,tr[rc(x)].sum);
	return;
}
inline void mule(int x,int v){
	if(!x) return;
	tr[x].sum=mul(tr[x].sum,v);
	tr[x].tag=mul(tr[x].tag,v);
	return;
}
inline void pushdown(int x){
	if(tr[x].tag!=1)
		mule(lc(x),tr[x].tag),mule(rc(x),tr[x].tag),tr[x].tag=1;
	return;
}
void change(int &k,int l,int r,int x,int v){
	if(!k) k=++cnt;
//	printf("qwq = %d\n",tr[x].tag);
	if(l==r) return tr[k].sum=v,void();
	int mid=(l+r)>>1;
	if(x<=mid) change(lc(k),l,mid,x,v);
	else change(rc(k),mid+1,r,x,v);
	pushup(k);
	return;
}
void merge(int &k,int x,int y,int l,int r,int &gu,int &gv){ // gu[i-1] gv[i-1]
//	printf("exe\n");
	if(!x&&!y) return k=0,void();
	if(!x){
		add(gv,tr[y].sum),mule(y,gu),k=y;
		return;
	}
	if(!y){
		add(gu,tr[x].sum),mule(x,gv),k=x;
		return;
	}
	if(l==r){
		int fu=tr[x].sum,fv=tr[y].sum;
		add(gv,fv),
		tr[x].sum=adc(1ll*tr[x].sum*gv%mod,1ll*gu*fv%mod),add(gu,fu);
		k=x;
		return;
	}
	int mid=(l+r)>>1;
	pushdown(x),pushdown(y);
	merge(lc(k),lc(x),lc(y),l,mid,gu,gv);
	merge(rc(k),rc(x),rc(y),mid+1,r,gu,gv);
	pushup(k);
	return;
}
int query(int k,int l,int r,int L,int R){
	if(!k) return 0;
	if(L<=l&&r<=R) return tr[k].sum;
	pushdown(k);
	int mid=(l+r)>>1,res=0;
	if(L<=mid) add(res,query(lc(k),l,mid,L,R));
	if(mid<R) add(res,query(rc(k),mid+1,r,L,R));
	return res;
}

void dfs(int i,int fa){
	int md=0,su,sv;
	dep[i]=dep[fa]+1;
	for(auto v:lim[i]) md=std::max(md,dep[v]);
	change(rt[i],0,n,md,1);
	for(auto v:G[i]){
		if(v==fa) continue;
		dfs(v,i),su=0,sv=query(rt[v],0,n,0,dep[i]);
		merge(rt[i],rt[i],rt[v],0,n,su,sv);
	}
	return;
}

int main(void){
	n=read();
	for(int i=1;i<n;++i){
		int u=read(),v=read();
		G[u].push_back(v),G[v].push_back(u); 
	}
	m=read();
	while(m--){
		int u=read(),v=read();
		lim[v].push_back(u);
	}
	dfs(1,0);
	
	printf("%d",query(rt[1],0,n,0,0));
	
	return 0;
} 

标签:return,命运,NOI2020,int,题解,sum,dep,cdots,rc
From: https://www.cnblogs.com/liuzongxin/p/17596116.html

相关文章

  • 国标GB28181视频平台LntonGBS(源码版)国标平台迁移服务器后无法启动的问题解决方案
    国标视频云服务LntonGBS支持设备/平台通过国标GB28181协议注册接入,并能实现视频的实时监控直播、录像、检索与回看、语音对讲、云存储、告警、平台级联等功能。平台部署简单、可拓展性强,支持将接入的视频流进行全终端、全平台分发,分发的视频流包括RTSP、RTMP、FLV、HLS、WebRTC等格......
  • 洛谷 U321190 麻将 加强加强版 题解
    Description给定一副\(k\)张牌的麻将牌,求能「听」哪些牌。对于所有数据,\(1\leqk\leq2\times10^5\)。link:https://www.luogu.com.cn/problem/U321190Solution算法零枚举「听」的牌,用状压DP或者贪心判断。时间复杂度\(\mathcal{O}(2^n\text{poly}(n))\)或\(\mathca......
  • DVWA靶场搭建过程 & 遇到的问题解决(apache标红、无法跳转等等)
    问题会在最后汇总解答第一步准备工作首先需要搭建PHP环境和获取DVWA源代码搭建PHP环境:搜索phpstudy→鼠标移动至windows版→点击phpstudy客户端→下滑,下载phpStudy2018Windows版本【注意,选择下载路径必须全英文】→获取到一个安装包,暂时不用解压。获取DVWA源代码:输入网站......
  • P1686 挑战 题解
    原题链接题目大意\(图上两个x或y值相同的点,如果其没有一条线段直接相连,则这两个点之间的距离为一条捷径\)\(给定一条路径,求此路径上最短的捷径长度(注意,是捷径最短)以及捷径的起止点和方向\)数据范围\(1\len\le250000\)\(先考虑x值相同的情况,假设有3个点A,B,C可以互相构成......
  • [JOI 2020 Final] 火事 题解
    题面给定一个长为\(N\)的序列\(S_i\),刚开始为时刻\(0\)。定义\(t\)时刻第\(i\)个数为\(S_i(t)\),那么:\[\left\{\begin{array}{ll}S_0(t)=0\\S_i(0)=S_i\\S_i(t)=\max\{S_{i-1}(t-1),S_i(t-1)\}\end{array}\right.\]共有\(Q\)个询问,每......
  • 【867】pgAdmin4 无法加载 loading 的问题解决
    ref:LoadingpgAdmin4v7.4...whileopeningpgAdminIhadthesameproblemwheninstallingpgAdminviathepostgresql-15.3-3-windows-x64installer.Solution:uninstallPostgreSQL;reinstallPostgreSQLbutinthecomponentsselection,uncheckPGAdmin;......
  • 【NOIP模拟题】我要的幸福 题解
    1.题意简述\(Zyh\)相信自己想要的幸福在不远处。然而,\(zyh\)想要得到这幸福,还需要很长的一段路。\(Zyh\)坚持认为整个人生可以抽象为一个\(n*m\)的棋盘。左上角的格子为\((1,1)\),右下角的格子为\((n,m)\)。整个棋盘上的格子都有不同的事件,因为生活的多姿多彩,事件的权值......
  • 2009NOIP普及组 题解
    第一题第二题\(一二题太简单就不在此处提了\)\(直接看到\)第三题细胞分裂题目大意\(有m1^{m2}个试管和n种细胞,第i种细胞初始有1个,每过1秒每一个会分裂成a_i个\)\(当有某种细胞可以平均分到试管中时开始实验,求开始实验的\)时间\((顺便说一下,我一开始没看到是时间,以为是求哪......
  • 洛谷-P9485 题解
    写在前面:这是蒟蒻交的第一篇绿题题解(大祭),因为线性做法比较难想,本篇会着重讲述用RMQ问题求解,并尽可能用清晰明了的图片和简易的文字讲明白。正文最坏时间复杂度:\(\mathcal{O}(\sumn+\log\sumn)\)在求解之前,先让我们想个问题,如何求解积水格数?再简单点,对于每个\(i\),其积水......
  • AcWing 4797. 移动棋子题解
    算出数值为\(1\)的点离\((3,3)\)的距离即可。#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;intmain(){intpx=-1,py=-1;for(inti=1;i<=5;i++){for(intj=1;j<=5;j++)......