【线段树 树链剖分 差分 经典技巧】loj#3046. 「ZJOI2019」语言【未完】
还是来致敬一下那过往吧
题目分析
先丢代码
#include<bits/stdc++.h>
const int maxn = ;
const int maxm = ;
const int maxNode = ; struct node
{
int top,son,fa,tot;
}a[maxn];
struct point
{
int u,v;
point(int a=, int b=):u(a),v(b) {}
};
struct tree
{
int ls,rs,cov,val;
}f[maxNode];
int n,m,tot;
long long ans,det;
int chain[maxn],chTot,rt[maxn];
int edgeTot,head[maxn],edges[maxm],nxt[maxm],dep[maxn];
std::vector<point> opt[maxn];
std::vector<int> inc[maxn],dec[maxn]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void addedge(int u, int v)
{
edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
}
void dfs1(int x, int fa)
{
dep[x] = dep[fa]+, a[x].tot = ;
a[x].top = a[x].son = -, a[x].fa = fa;
for (int i=head[x]; i!=-; i=nxt[i])
{
int v = edges[i];
if (v==fa) continue;
dfs1(v, x), a[x].tot += a[v].tot;
if (a[x].son==-||a[a[x].son].tot < a[v].tot)
a[x].son = v;
}
}
void dfs2(int x, int top)
{
a[x].top = top, chain[x] = ++chTot;
if (a[x].son==-) return;
dfs2(a[x].son, top);
for (int i=head[x]; i!=-; i=nxt[i])
if (edges[i]!=a[x].fa&&edges[i]!=a[x].son)
dfs2(edges[i], edges[i]);
}
void splitChain(int id, int u, int v)
{
inc[u].push_back(id), inc[v].push_back(id);
while (a[u].top!=a[v].top)
{
if (dep[a[u].top] > dep[a[v].top]) std::swap(u, v);
opt[id].push_back(point(chain[a[v].top], chain[v]));
v = a[a[v].top].fa;
}
if (dep[u] > dep[v]) std::swap(u, v);
opt[id].push_back(point(chain[u], chain[v]));
dec[u].push_back(id), dec[a[u].fa].push_back(id);
}
void pushup(int rt, int len)
{
if (f[rt].cov) f[rt].val = len;
else f[rt].val = f[f[rt].ls].val+f[f[rt].rs].val;
}
void mergeSeg(int &u, int v, int l, int r)
{
if (!u||!v) u += v;
else{
int mid = (l+r)>>;
f[u].cov += f[v].cov;
mergeSeg(f[u].ls, f[v].ls, l, mid);
mergeSeg(f[u].rs, f[v].rs, mid+, r);
}
pushup(u, r-l+);
}
void update(int &rt, int L, int R, int l, int r, int c)
{
if (!rt) rt = ++tot;
if (L <= l&&r <= R) f[rt].cov += c, pushup(rt, r-l+);
else{
int mid = (l+r)>>;
if (L <= mid) update(f[rt].ls, L, R, l, mid, c);
if (R > mid) update(f[rt].rs, L, R, mid+, r, c);
}
pushup(rt, r-l+);
}
void delta(int x, int fa)
{
for (int i=head[x]; i!=-; i=nxt[i])
if (edges[i]!=fa) delta(edges[i], x);
for (int l=; l<inc[x].size(); l++)
for (int i=,mx=opt[inc[x][l]].size(); i<mx; i++)
update(rt[x], opt[inc[x][l]][i].u, opt[inc[x][l]][i].v, , n, );
for (int l=; l<dec[x].size(); l++)
for (int i=,mx=opt[dec[x][l]].size(); i<mx; i++)
update(rt[x], opt[dec[x][l]][i].u, opt[dec[x][l]][i].v, , n, -);
int val = f[rt[x]].val;
if (val) ans += val, ++det;
mergeSeg(rt[fa], rt[x], , n);
}
int main()
{
memset(head, -, sizeof head);
n = read(), m = read();
for (int i=; i<n; i++)
addedge(read(), read());
dfs1(, ), dfs2(, );
for (int i=; i<=m; i++)
splitChain(i, read(), read());
delta(, );
printf("%lld\n",(ans-det)/);
return ;
}
【线段树 树链剖分 差分 经典技巧】loj#3046. 「ZJOI2019」语言【未完】的更多相关文章
- bzoj5518 & loj3046 「ZJOI2019」语言 线段树合并+树链的并
题目传送门 https://loj.ac/problem/3046 题解 首先问题就是问有多少条路径是给定的几条路径中的一条的一个子段. 先考虑链的做法. 枚举右端点 \(i\),那么求出 \(j\) ...
- @loj - 3043@「ZJOI2019」线段树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 九条可怜是一个喜欢数据结构的女孩子,在常见的数据结构中,可怜最喜 ...
- 【LOJ】#3043. 「ZJOI2019」线段树
LOJ#3043. 「ZJOI2019」线段树 计数转期望的一道好题-- 每个点设两个变量\(p,q\)表示这个点有\(p\)的概率有标记,有\(q\)的概率到祖先的路径上有个标记 被覆盖的点$0.5 ...
- LOJ #2359. 「NOIP2016」天天爱跑步(倍增+线段树合并)
题意 LOJ #2359. 「NOIP2016」天天爱跑步 题解 考虑把一个玩家的路径 \((x, y)\) 拆成两条,一条是 \(x\) 到 \(lca\) ( \(x, y\) 最近公共祖先) 的 ...
- Loj #2570. 「ZJOI2017」线段树
Loj #2570. 「ZJOI2017」线段树 题目描述 线段树是九条可怜很喜欢的一个数据结构,它拥有着简单的结构.优秀的复杂度与强大的功能,因此可怜曾经花了很长时间研究线段树的一些性质. 最近可怜 ...
- loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点
loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点 链接 loj 思路 用交错关系建出图来,发现可以直接缩点,拓扑统计. 完了吗,不,瓶颈在于边数太多了,线段树优化建图. 细节 ...
- 「ZJOI2019」线段树 解题报告
「ZJOI2019」线段树 听说有人喷这个题简单,然后我就跑去做,然后自闭感++,rp++(雾) 理性分析一波,可以发现最后形成的\(2^k\)个线段树,对应的操作的一个子集,按时间顺序作用到这颗线段 ...
- loj#2665. 「NOI2013」树的计数
目录 题目链接 题解 代码 题目链接 loj#2665. 「NOI2013」树的计数 题解 求树高的期望 对bfs序分层 考虑同时符合dfs和bfs序的树满足什么条件 第一个点要强制分层 对于bfs序 ...
- HDU 5452——Minimum Cut——————【树链剖分+差分前缀和】ACdream 1429——Diversion——————【树链剖分】
Minimum Cut Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)Tota ...
随机推荐
- java基础第十二篇之集合、增强for循环、迭代器和泛型
Collection接口中的常用方法: * 所有的子类子接口都是具有的 * 集合的方法:增删改查 * * public boolean add(E e);//添加元素 返回值表示是否添加成功 * pu ...
- .bat 文件学习
参考文章:http://www.cnblogs.com/glaivelee/archive/2009/10/07/1578737.html 重点: @echo off 关闭回显,不显示脚本中的命令 e ...
- vue路由的四种传值
第一种:props 配置: 组件内定义: props: ['id'] 路由映射配置,开启props:true : { path: '/user/:id', component: User, props ...
- iOS 隐藏百度地图SDK的百度LOGO
第一个思路:找到LOGO对应的UIIMageView,并将其隐藏hidden // 隐藏百度地图Logo UIView *mView = _mapView.subviews.firstObject; ...
- 如何使用sass
Sass 是对 CSS 的扩展,让 CSS 语言更强大.优雅. 它允许你使用变量.嵌套规则.mixin.导入等众多功能, 并且完全兼容 CSS 语法. Sass 有助于保持大型样式表结构良好, 同时也 ...
- linux 01 基础命令
linux 01 基础命令 对于Linux要记住一个概念,一切皆文件,哪怕是目录,也是一个文件 1.修改用户密码 sudo passwd pyvip@Vip:~$ #pyvip表示用户名, Vip表示 ...
- HDU-2119-Matrix(最大匹配)
链接:https://vjudge.net/problem/HDU-2119#author=Smilencer 题意: 众所周知,tyz是一个写bug小能手,以至于如果没有队友的帮助,就ac不了程序. ...
- CentOS,net core2 sdk nginx、supervisor、mysql
CentOS下 .net core2 sdk nginx.supervisor.mysql环境搭建 作为.neter,看到.net core 2.0的正式发布,心里是有点小激动的,迫不及待的体验了一把 ...
- 048 Rotate Image 旋转图像
给定一个 n × n 的二维矩阵表示一个图像.将图像旋转 90 度(顺时针).注意:你必须在原矩阵中旋转图像,请不要使用另一个矩阵来旋转图像.例 1:给出的输入矩阵 = [ [1,2,3], [4 ...
- linux-ubuntu下调出中文输入法
linux-ubuntu下调出中文输入法 注:此方法我并没有亲身实践过,只是觉得可能会用到,所以保存一下