题目描述



题解

吼题但题解怎么这么迷

考虑一种和题解不同的做法(理解)

先把僵尸离散化,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】僵尸的更多相关文章

  1. 6389. 【NOIP2019模拟2019.10.26】小w学图论

    题目描述 题解 之前做过一次 假设图建好了,设g[i]表示i->j(i<j)的个数 那么ans=∏(n-g[i]),因为连出去的必定会构成一个完全图,颜色互不相同 从n~1染色,点i的方案 ...

  2. 6377. 【NOIP2019模拟2019.10.05】幽曲[埋骨于弘川]

    题目描述 题解 随便bb 详细题解见 https://www.cnblogs.com/coldchair/p/11624979.html https://blog.csdn.net/alan_cty/ ...

  3. 【NOIP2019模拟2019.10.07】果实摘取 (约瑟夫环、Mobius反演、类欧、Stern-Brocot Tree)

    Description: 小 D 的家门口有一片果树林,果树上果实成熟了,小 D 想要摘下它们. 为了便于描述问题,我们假设小 D 的家在二维平面上的 (0, 0) 点,所有坐标范围的绝对值不超过 N ...

  4. 6383. 【NOIP2019模拟2019.10.07】果实摘取

    题目 题目大意 给你一个由整点组成的矩形,坐标绝对值范围小于等于\(n\),你在\((0,0)\),一开始面向\((1,0)\),每次转到后面第\(k\)个你能看到的点,然后将这条线上的点全部标记删除 ...

  5. 6380. 【NOIP2019模拟2019.10.06】小w与最长路(path)

    题目 题目大意 给你一棵树,对于每一条边,求删去这条边之后,再用一条边(自己定)连接两个连通块,形成的树的直径最小是多少. 正解 首先,将这棵树的直径给找出来.显然,如果删去的边不在直径上,那么答案就 ...

  6. 6374. 【NOIP2019模拟2019.10.04】结界[生与死的境界]

    题目 题目大意 给你一个数列,每次可以选择任意两个相邻的数\(x\)和\(y\),将其删去,并在原来位置插入\(x+2y\). 每次询问一个区间,对这个区间进行上述操作.求最后剩下的数最大是多少. 答 ...

  7. 2019.10.26 csp-s模拟测试88 反思总结

    今天的主人公是什么? 60.1K!!!! 先扔代码再更新防止我等会儿一上头不打算写完题解 T1: #include<iostream> #include<cstdio> #in ...

  8. 2019.10.26 CSP%您赛第三场

    \(CSP\)凉心模拟^_^ --题源\(lqx.lhc\)等各位蒟蒻 题目名称 比赛 传递消息 开关灯 源文件名 \(competition.cpp\) \(message.cpp\) \(ligh ...

  9. 6424. 【NOIP2019模拟2019.11.13】我的订书机之恋

    题目描述 Description Input Output Sample Input 见下载 Sample Output 见下载 Data Constraint 题解 lj题卡线段树 求出每个右端点往 ...

随机推荐

  1. Ehlib好用的版本

    EhLib 6.2

  2. JS获取URL中参数值

    一.正则法: function getQueryString(name) { var reg = new RegExp('(^|&)' + name + '=([^&]*)(& ...

  3. 【ABAP系列】SAP ABAP系统变量及注释

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP系统变量及注释 ...

  4. 【Qt开发】【VS开发】VS2010+Qt开发环境搭建

    QT与JAVA有点类似,也是一种跨平台的软件(当然在windows平台和linux平台需要安装相应的QT开发环境和运行库,类似于JAVA在不同平台下的虚拟机JVM环境),因此对于某些需要同时支持win ...

  5. Express中间件body-parser

    在http请求种,POST.PUT.PATCH三种请求方法中包含着请求体,也就是所谓的request,在Nodejs原生的http模块中,请求体是要基于流的方式来接受和解析. body-parser是 ...

  6. 一、Zabbix-学习列表

    近期本人在求职,面试了几家,觉得监控是一个很重要的事情,所以决定深入学习一下监控.目前的监控系统有很多,Zabbix是目前应用最广泛的开源监控之一,功能比较完善,所以决定学习一下. 目前将学习zabb ...

  7. GCC 编译参数

    -s 这个参数会把符号表从最终的可执行文件中删除.没有符号表,你就不能用gdb调试了,但是程序会更小 -O0 不做任何优化,这是默认的编译选项 -c 只编译不链接,产生.o文件,就是obj文件,不产生 ...

  8. 解决org.apache.subversion.javahl.ClientException的方法【】

    重新刷新项目,配置项目,总是报“The project was not built due to "org.apache.subversion.javahl.ClientException” ...

  9. list 转 map java8

    // Arrays.asList("a:1.0", "b:2.0", "c:3.0") --> Map {a=1.0, b=2.0, ...

  10. Spark启动流程(Standalone)-分析

    1.start-all.sh脚本,实际上执行java -cp Master 和 java -cp Worker 2.Master 启动时首先穿件一个RpcEnv对象,负责管理所有通信逻辑 3.Mast ...