6392. 【NOIP2019模拟2019.10.26】僵尸
题目描述
题解
吼题但题解怎么这么迷
考虑一种和题解不同的做法(理解)
先把僵尸离散化,h相同的钦(ying)点一个大小
(可以发现这样每种情况只会被算正好一次)
计算完全被占领的方案,然后1-方案/概率
由于大小确定了,所以最后会被分成若干不相连的块,且块中至少有一只僵尸,大的僵尸能占领小的僵尸的块,所以相邻两块之间一定会断开
那么一种占领的方案对应的是一类高度情况,考虑所有的占领方案即可求出所有的高度情况
定义一个块的编号为所占领的最大僵尸的编号
设f[i]x表示以i为根的子树中点i所在块的编号为x
那么对于f[j]y转移如下:
①x=y
f[j][y]*(僵尸x经过i--j的方案数)-->f[i][x]
那么x和y在同一个块中,因为一个块只有一只僵尸,所以块内必须要连通
②x<y
f[j][y]*(僵尸y不经过i--j的方案数)-->f[i][x]
x和y不在同一个块中,所以x和y不能连通,即较大的僵尸(y)不能走到另一个点(i)
并且要保证j中存在y,不存在x,原因见下文
③x>y
f[j][y]*(僵尸x不经过i--j的方案数)-->f[i][x]
原因&范围同上
初值为f[i][x]=[x>=i处最大的僵尸能力值](x>0)
对于②③的限制:
因为要保证以某个点i为最浅点的块内刚好存在僵尸x,
在i与fa[i]断开时保证了x在i的子树中,i所在块的叶子与块中叶子的儿子断开保证了x不在块外,所以块中必定存在x
时间复杂度O(n3),前后缀优化成O(n2)
code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%998244353
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define mod 998244353
#define Mod 998244351
using namespace std;
struct type{
int x,id;
} b[2001];
int a[4002][2];
int c[2001][2001];
int C[2001];
int ls[2001];
int L[2001];
int R[2001];
int h[2001];
int H[2001];
long long f[2001][2001];
long long s1[2002];
long long s2[2002];
bitset<2001> bz[2001];
int T,N,n,m,i,j,k,l,len;
long long ans,s;
bool cmp(type a,type b)
{
return a.x<b.x;
}
void New(int x,int y)
{
++len;
a[len][0]=y;
a[len][1]=ls[x];
ls[x]=len;
}
long long qpower(long long a,int b)
{
long long ans=1;
while (b)
{
if (b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void Dfs(int Fa,int t)
{
int i;
if (h[t]) bz[t][h[t]]=1;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
Dfs(t,a[i][0]);
bz[t]|=bz[a[i][0]];
}
}
void dfs(int Fa,int t)
{
int i,j,k,l,id;
long long x;
fo(i,max(1,h[t]),N) f[t][i]=1;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
id=i/2;
dfs(t,a[i][0]);
fo(k,1,N)
{
s1[k]=s1[k-1];
if (bz[a[i][0]][k])
add(s1[k],f[a[i][0]][k]);
}
s2[N+1]=0;
fd(k,N,1)
{
s2[k]=s2[k+1];
if (bz[a[i][0]][k])
add(s2[k],f[a[i][0]][k]*max(R[id]-max(H[k],L[id])+1,0)%mod);
}
fo(j,1,N)
{
if (!bz[a[i][0]][j])
f[t][j]=f[t][j]*(s2[j+1]+s1[j-1]*max(R[id]-max(H[j],L[id])+1,0)%mod+f[a[i][0]][j]*max(min(H[j]-1,R[id])-L[id]+1,0)%mod)%mod;
else
f[t][j]=f[t][j]*(f[a[i][0]][j]*max(min(H[j]-1,R[id])-L[id]+1,0)%mod)%mod;
// O(n^3)
// fo(k,1,N)
// if (f[a[i][0]][k])
// {
// if (j<k)
// x=max(R[id]-max(H[k],L[id])+1,0);
// if (j==k)
// x=max(min(H[k]-1,R[id])-L[id]+1,0);
// if (j>k)
// x=max(R[id]-max(H[j],L[id])+1,0);
//
// if (j==k || bz[a[i][0]][k] && !bz[a[i][0]][j])
// add(F[j],f[t][j]*f[a[i][0]][k]%mod*x);
// }
}
}
}
int main()
{
freopen("zombie.in","r",stdin);
freopen("zombie.out","w",stdout);
scanf("%d",&T);
for (;T;--T)
{
memset(bz,0,sizeof(bz));
memset(ls,0,sizeof(ls));
memset(h,0,sizeof(h));
memset(H,0,sizeof(H));
memset(f,0,sizeof(f));
memset(C,0,sizeof(C));
len=1;
scanf("%d%d",&n,&m);
fo(i,1,n-1)
{
scanf("%d%d%d%d",&j,&k,&L[i],&R[i]);
New(j,k);
New(k,j);
}
fo(i,1,m)
{
scanf("%d%d",&j,&k);
h[j]=max(h[j],k);
}
N=0;
fo(i,1,n)
if (h[i])
b[++N]={h[i],i};
sort(b+1,b+N+1,cmp);
fo(i,1,N)
{
H[i]=b[i].x;
h[b[i].id]=i;
}
Dfs(0,1);
dfs(0,1);
ans=0;
fo(i,1,N)
add(ans,f[1][i]);
s=1;
fo(i,1,n-1)
s=s*(R[i]-L[i]+1)%mod;
ans=ans*qpower(s,Mod)%mod;
printf("%lld\n",((1-ans)%mod+mod)%mod);
}
fclose(stdin);
fclose(stdout);
return 0;
}
6392. 【NOIP2019模拟2019.10.26】僵尸的更多相关文章
- 6389. 【NOIP2019模拟2019.10.26】小w学图论
题目描述 题解 之前做过一次 假设图建好了,设g[i]表示i->j(i<j)的个数 那么ans=∏(n-g[i]),因为连出去的必定会构成一个完全图,颜色互不相同 从n~1染色,点i的方案 ...
- 6377. 【NOIP2019模拟2019.10.05】幽曲[埋骨于弘川]
题目描述 题解 随便bb 详细题解见 https://www.cnblogs.com/coldchair/p/11624979.html https://blog.csdn.net/alan_cty/ ...
- 【NOIP2019模拟2019.10.07】果实摘取 (约瑟夫环、Mobius反演、类欧、Stern-Brocot Tree)
Description: 小 D 的家门口有一片果树林,果树上果实成熟了,小 D 想要摘下它们. 为了便于描述问题,我们假设小 D 的家在二维平面上的 (0, 0) 点,所有坐标范围的绝对值不超过 N ...
- 6383. 【NOIP2019模拟2019.10.07】果实摘取
题目 题目大意 给你一个由整点组成的矩形,坐标绝对值范围小于等于\(n\),你在\((0,0)\),一开始面向\((1,0)\),每次转到后面第\(k\)个你能看到的点,然后将这条线上的点全部标记删除 ...
- 6380. 【NOIP2019模拟2019.10.06】小w与最长路(path)
题目 题目大意 给你一棵树,对于每一条边,求删去这条边之后,再用一条边(自己定)连接两个连通块,形成的树的直径最小是多少. 正解 首先,将这棵树的直径给找出来.显然,如果删去的边不在直径上,那么答案就 ...
- 6374. 【NOIP2019模拟2019.10.04】结界[生与死的境界]
题目 题目大意 给你一个数列,每次可以选择任意两个相邻的数\(x\)和\(y\),将其删去,并在原来位置插入\(x+2y\). 每次询问一个区间,对这个区间进行上述操作.求最后剩下的数最大是多少. 答 ...
- 2019.10.26 csp-s模拟测试88 反思总结
今天的主人公是什么? 60.1K!!!! 先扔代码再更新防止我等会儿一上头不打算写完题解 T1: #include<iostream> #include<cstdio> #in ...
- 2019.10.26 CSP%您赛第三场
\(CSP\)凉心模拟^_^ --题源\(lqx.lhc\)等各位蒟蒻 题目名称 比赛 传递消息 开关灯 源文件名 \(competition.cpp\) \(message.cpp\) \(ligh ...
- 6424. 【NOIP2019模拟2019.11.13】我的订书机之恋
题目描述 Description Input Output Sample Input 见下载 Sample Output 见下载 Data Constraint 题解 lj题卡线段树 求出每个右端点往 ...
随机推荐
- Ehlib好用的版本
EhLib 6.2
- JS获取URL中参数值
一.正则法: function getQueryString(name) { var reg = new RegExp('(^|&)' + name + '=([^&]*)(& ...
- 【ABAP系列】SAP ABAP系统变量及注释
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP系统变量及注释 ...
- 【Qt开发】【VS开发】VS2010+Qt开发环境搭建
QT与JAVA有点类似,也是一种跨平台的软件(当然在windows平台和linux平台需要安装相应的QT开发环境和运行库,类似于JAVA在不同平台下的虚拟机JVM环境),因此对于某些需要同时支持win ...
- Express中间件body-parser
在http请求种,POST.PUT.PATCH三种请求方法中包含着请求体,也就是所谓的request,在Nodejs原生的http模块中,请求体是要基于流的方式来接受和解析. body-parser是 ...
- 一、Zabbix-学习列表
近期本人在求职,面试了几家,觉得监控是一个很重要的事情,所以决定深入学习一下监控.目前的监控系统有很多,Zabbix是目前应用最广泛的开源监控之一,功能比较完善,所以决定学习一下. 目前将学习zabb ...
- GCC 编译参数
-s 这个参数会把符号表从最终的可执行文件中删除.没有符号表,你就不能用gdb调试了,但是程序会更小 -O0 不做任何优化,这是默认的编译选项 -c 只编译不链接,产生.o文件,就是obj文件,不产生 ...
- 解决org.apache.subversion.javahl.ClientException的方法【】
重新刷新项目,配置项目,总是报“The project was not built due to "org.apache.subversion.javahl.ClientException” ...
- list 转 map java8
// Arrays.asList("a:1.0", "b:2.0", "c:3.0") --> Map {a=1.0, b=2.0, ...
- Spark启动流程(Standalone)-分析
1.start-all.sh脚本,实际上执行java -cp Master 和 java -cp Worker 2.Master 启动时首先穿件一个RpcEnv对象,负责管理所有通信逻辑 3.Mast ...