题目描述



题解

吼题但题解怎么这么迷

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

先把僵尸离散化,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. Unity—Compoent类

    官方API->Componment   新引入成员 作用 字段 gameobject 该组件所在的游戏对象 tag 游戏对象的标签 Transform 添加在游戏对象上的transform组件 ...

  2. Spring MVC 中RequestContextHolder获取request和response

    1.最简单方式:处理方法入参 例如: @RequestMapping("/test") @ResponseBody public void saveTest(HttpServlet ...

  3. DedeCMS调取其他织梦CMS站点数据库数据方法

    第1步:打开网站include\taglib文件夹中找到sql.lib.php文件,并直接复制一些此文件出来,并把复制出来的这个文件重命名为mysql.lib.php.注:mysql.lib.php, ...

  4. 强化学习之MDP

    前言 最近又入坑RL了,要搞AutoML就要学会RL,真的是心累.. 正文 MDP里面比较重要的就是状态值函数和动作-状态值函数吧,然后再求最优状态值函数和最优动作状态值函数,状态值函数的公式推导一开 ...

  5. python+selenium下弹窗alter对象处理02

    首先使用switch_to.alert()方法进行定位,然后可以使用下面的操作 text:返回alert.confirm.prompt中的文字信息: accept():接受现有警告框: dismiss ...

  6. HTTP 常见相应状态码及含义

    1xx:信息 100 Continue 服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求. 101 Switching Protocols 服务器转换协议:服务器将 ...

  7. QQ管理

    ##用例1:查询数据 #01.查询QQ号码为54789625的所有好友信息,包括QQ号码,昵称,年龄 # # SELECT `relation`.RelationQQID AS QQ号码,`basei ...

  8. selectnodes和selectSingleNode

    selectnodes: selectNodes和ChildNodes获取XML内容数组的差异性 我们在使用XML进行查询或者变更数据的时候,需要注意两个很相近但结果相差很大的用法,如下: 1: Xm ...

  9. Javascript高级面试

    原型 异步 一.什么是单线程,和异步有什么关系 单线程:只有一个线程,同一时间只能做一件事原因:避免DOM渲染的冲突解决方案:异步 为什么js只有一个线程:避免DOM渲染冲突 浏览器需要渲染DOM J ...

  10. 使用Log4Net将系统日志信息记录到记事本和数据库中

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/hxpjava1/article/details/32714855 一.使用Log4Net将日志记录到 ...