跟仙人掌其实没啥关系…

Here

注意 每一次都O(n)O(n)O(n)一下算某些点都是黑点的概率其实并不是O(n2)O(n^2)O(n2),因为每个环只用算一次.

#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 100005;
const int MAXM = 250005;
const int mod = 998244353;
inline void read(int &num) {
char ch; while(!isdigit(ch=getchar()));
for(num=0; isdigit(ch); num=num*10+ch-'0',ch=getchar());
}
inline int qmul(int a, int b) {
int res = 1;
while(b) {
if(b&1) res = 1ll * res * a % mod;
a = 1ll * a * a % mod; b >>= 1;
}
return res;
}
int n, m, t, w, bjc[MAXN], u[MAXM], v[MAXM]; bool in[MAXM];
int find(int x) { return bjc[x] == x ? x : bjc[x] = find(bjc[x]); }
namespace pou {
int fir[MAXN], cnt; struct edge { int to, nxt; }e[MAXN<<1];
inline void addedge(int x, int y) { e[cnt] = (edge){ y, fir[x] }, fir[x] = cnt++; }
int sz[MAXN], top[MAXN], fa[MAXN], son[MAXN], dep[MAXN], dfn[MAXN], tmr, seq[MAXN];
inline void dfs1(int u, int ff) {
dep[u] = dep[fa[u]=ff] + (sz[u]=1);
for(int v, i = fir[u]; ~i; i = e[i].nxt)
if((v=e[i].to) != ff) {
dfs1(v, u), sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
}
inline void dfs2(int u, int tp) {
top[u] = tp; seq[dfn[u]=++tmr] = u;
if(son[u]) dfs2(son[u], tp);
for(int v, i = fir[u]; ~i; i = e[i].nxt)
if((v=e[i].to) != fa[u] && v != son[u])
dfs2(v, v);
}
bool col[MAXN<<2], lz[MAXN<<2];
void upd(int i) { col[i] = col[i<<1] | col[i<<1|1]; }
void mt(int i) {
if(lz[i]) {
lz[i<<1] = lz[i<<1|1] = col[i<<1] = col[i<<1|1] = 1;
lz[i] = 0;
}
}
void cover(int i, int l, int r, int x, int y) {
if(l == x && r == y) {
col[i] = lz[i] = 1;
return;
}
mt(i);
int mid = (l + r) >> 1;
if(y <= mid) cover(i<<1, l, mid, x, y);
else if(x > mid) cover(i<<1|1, mid+1, r, x, y);
else cover(i<<1, l, mid, x, mid), cover(i<<1|1, mid+1, r, mid+1, y);
upd(i);
}
inline int Cover(int x, int y) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
cover(1, 1, n, dfn[top[x]], dfn[x]); x = fa[top[x]];
}
if(x == y) return x;
if(dep[x] < dep[y]) swap(x, y);
cover(1, 1, n, dfn[y]+1, dfn[x]);
return y;
}
bool query(int i, int l, int r, int x, int y) {
if(l == x && r == y) return col[i];
mt(i);
int mid = (l + r) >> 1; bool res;
if(y <= mid) res = query(i<<1, l, mid, x, y);
else if(x > mid) res = query(i<<1|1, mid+1, r, x, y);
else res = (query(i<<1, l, mid, x, mid) || query(i<<1|1, mid+1, r, mid+1, y));
upd(i); return res;
}
inline bool Query(int x, int y) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
if(query(1, 1, n, dfn[top[x]], dfn[x])) return 1;
x = fa[top[x]];
}
if(x == y) return 0;
if(dep[x] < dep[y]) swap(x, y);
return query(1, 1, n, dfn[y]+1, dfn[x]);
}
}
int P[MAXN], ans[2], inv[MAXN], fac[MAXN], MULT[MAXN];
inline void pre(int N) {
inv[0] = inv[1] = fac[0] = fac[1] = 1;
for(int i = 2; i <= N; ++i)
fac[i] = 1ll * fac[i-1] * i % mod, inv[i] = 1ll * (mod - mod/i) * inv[mod%i] % mod;
for(int i = 2; i <= N; ++i)
inv[i] = 1ll * inv[i-1] * inv[i] % mod;
for(int i = 2; i <= N; ++i) MULT[i] = qmul(i, t);
}
inline int C(int n, int m) {
if(m > n) return 0;
return 1ll * fac[n] * inv[m] % mod * inv[n-m] % mod;
}
int all, invall, invn, POINT, EDGE, f[MAXN];
inline int solve(int i) {
if(!i || i > t) return 0;
if(~f[i]) return f[i]; //记忆化一下
int res = all;
for(int j = 1, flg = 1; j <= i; flg *= -1, ++j)
res = (res - 1ll * flg * C(i, j) * MULT[n-j] % mod) % mod;
return f[i] = 1ll * res * invall % mod;
}
int main () {
freopen("cactus.in", "r", stdin);
freopen("cactus.out", "w", stdout);
read(n), read(m), read(t), read(w); pre(n);
memset(f, -1, sizeof f);
all = qmul(n, t), invall = qmul(all, mod-2), invn = qmul(n, mod-2);
for(int i = 1; i < n; ++i) P[i] = qmul(1ll*(n-i)*invn%mod, t); ans[0] = 1ll * P[1] * n % mod;
ans[1] = 1ll * (POINT=solve(1)) * n % mod;
EDGE = solve(2);
for(int i = 1; i <= n; ++i) bjc[i] = i, pou::fir[i] = -1;
for(int i = 1; i <= m; ++i) {
read(u[i]), read(v[i]);
int x = find(u[i]), y = find(v[i]);
if(x != y) { in[i] = 1;
pou::addedge(u[i], v[i]);
pou::addedge(v[i], u[i]);
bjc[y] = x;
}
}
for(int i = 1; i <= n; ++i)
if(!pou::sz[i]) pou::dfs1(i, 0), pou::dfs2(i, i);
for(int i = 1; i <= m; ++i) {
if(in[i]) {
ans[0] = (ans[0] - P[2]) % mod;
if(w)ans[1] = (ans[1] - EDGE) % mod;
}
else if(pou::Query(u[i], v[i]) == 0) {
ans[0] = (ans[0] - P[2]) % mod;
if(w)ans[1] = (ans[1] - EDGE) % mod;
int lca = pou::Cover(u[i], v[i]);
int len = pou::dep[u[i]] + pou::dep[v[i]] - (pou::dep[lca]<<1) + 1;
ans[0] = (ans[0] + P[len]) % mod;
if(w) ans[1] = (ans[1] + solve(len)) % mod;
}
printf("%d\n", w ? ((ans[0] + ans[1]) % mod + mod) % mod : (ans[0]+mod) % mod);
}
}

JZOJ 5987 仙人掌毒题 (树链剖分 + 容斥)的更多相关文章

  1. bzoj 3589: 动态树【树链剖分+容斥】

    因为一开始调试不知道unsigned怎么输出就没有加\n结果WA了一上午!!!!!然而最后放弃了unsigned选择了&2147483647 首先链剖,因为它所给的链一定是某个点到根的路径上的 ...

  2. bzoj3589 动态树 树链剖分+容斥

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3589 题解 事件 \(0\) 不需要说,直接做就可以了. 事件 \(1\) 的话,考虑如果直接 ...

  3. [luogu3676] 小清新数据结构题 [树链剖分+线段树]

    题面 传送门 思路 本来以为这道题可以LCT维护子树信息直接做的,后来发现这样会因为splay形态改变影响子树权值平方和,是splay本身的局限性导致的 所以只能另辟蹊径 首先,我们考虑询问点都在1的 ...

  4. 2019 icpc南昌全国邀请赛-网络选拔赛J题 树链剖分+离线询问

    链接:https://nanti.jisuanke.com/t/38229 题意: 给一棵树,多次查询,每次查询两点之间权值<=k的边个数 题解: 离线询问,树链剖分后bit维护有贡献的位置即可 ...

  5. HYSBZ 1036 树的统计Count (水题树链剖分)

    题意:中文题. 析:就是直接维护一个最大值和一个和,用线段树维护即可,这个题很简单,但是我卡了一晚上,就是在定位的时候,位置直接反过来了,但是样例全过了...真是... 代码如下: #pragma c ...

  6. 洛谷 U14475 部落冲突 【比赛】 【树链剖分 + 线段树】

    题目背景 在一个叫做Travian的世界里,生活着各个大大小小的部落.其中最为强大的是罗马.高卢和日耳曼.他们之间为了争夺资源和土地,进行了无数次的战斗.期间诞生了众多家喻户晓的英雄人物,也留下了许多 ...

  7. POJ2763 Housewife Wind 树链剖分 边权

    POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...

  8. HDU3669 Aragorn's Story 树链剖分 点权

    HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...

  9. jzoj5987. 【WC2019模拟2019.1.4】仙人掌毒题 (树链剖分+概率期望+容斥)

    题面 题解 又一道全场切的题目我连题目都没看懂--细节真多-- 先考虑怎么维护仙人掌.在线可以用LCT,或者像我代码里先离线,并按时间求出一棵最小生成树(或者一个森林),然后树链剖分.如果一条边不是生 ...

随机推荐

  1. 阿里EMR部署

    选自定义购买: 选择master配置: 选择core配置: 下一步,选高级里在jdbc后填RDS的url, 用户名,密码: jdbc:mysql://rm-d7o7x76l11u0434zn.mysq ...

  2. java23种设计模式之五:代理模式

    一.代理模式介绍 代理模式的定义:就是为一个接品(对象)提供一个代理的对象,并由这个代理对象控制对原对象的访问流程 其中代理又分为:静态代理和动态代理 静态代理:指的是自己要写一个代理类,或者用工具生 ...

  3. Spring的Bean的生命周期(大众版)

      距离上一次写Spring源码解析,已经过去了快要好几个月了,主要原因还是Spring的源码解析类文章太难写了,不像我先前写的什么CAS源码,AQS源码,LinkedBlockingQueue等等, ...

  4. 烯烃(olefin) 题解

    题面 对于每个点,我们可以用一次dfs求出这个点到以这个点为字树的最远距离和次远距离: 然后用换根法再来一遍dfs求出这个点到除这个点子树之外的最远距离: 显然的,每次的询问我们可以用向上的最大值加向 ...

  5. win7安装mongodb3.6

    1. 下载 https://www.mongodb.com/download-center/enterprise 选择合适平台点击下载 2. 安装mongodb 在win7系统安装mongodb需要v ...

  6. k8s基础知识

    k8s部署到云计算上的优势 传统模式: 在k8s外部部署一个外置调度器,请求先到物理node节点ip地址,由物理服务地址再转发代理至service地址,如果node节点也是私网地址呢,就需要再外部部署 ...

  7. 老贾的幸福生活day3 之markdown常用语法简要

    1.markdown常用语法 标题 一级到六级 用#+空格实现 2.代码块 3个 `实现 python is a ...... 单行代码,用"``" 3.列表 有序列表 跟内容 数 ...

  8. jwt认证规则

    目录 认证规则图 django不分离 drf分类 认证规则演变图 数据库session认证:低效 缓存认证:高效 jwt认证:高效 缓存认证:不易并发 jwt认证:易并发 JWT认证规则 优点 格式 ...

  9. pat L2--005 简单复习一下并差集

    布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位.无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席. 输入格式: ...

  10. B2C电商平台开发心得(asp.net+bootstrap)

    Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 html.css.javascript的,专为 web 应用设计,包含了移动设备优先的样式, 其响应式 ...