【线段树 树链剖分 差分 经典技巧】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 ...
随机推荐
- 《SQL 进阶教程》 case:在 CASE 表达式中使用聚合函数
1.只加入一个社团的学生的社团id select std_id, max(club_id) from student_clubgroup by std_idhaving count(*) =1---- ...
- 如何使用localStorage?
首先使用localStorage的时候,我们需要判断浏览器是否支持localStorage这个属性. if(!window.localStorage){ alert("浏览器支持locals ...
- Python面向对象之鸭子类型
python没有多态?他有什么? 他有鸭子类型. 鸭子类型 : 看着像鸭子,他就是鸭子. 比如一些类,他们中有一些方法,有着相同的功能, 这时为我们将这些相同功能的名字命名为一样的. 那么这些类 都互 ...
- 详解javascript中的this对象
详解javascript中的this对象 前言 Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象.Javascript可以通过一定的 ...
- java中实现定时任务 task 或quartz
转载大神的 https://www.cnblogs.com/hafiz/p/6159106.html https://www.cnblogs.com/luchangyou/p/6856725.html ...
- java-可逆加密算法
转载大神的 https://blog.csdn.net/want_water_fish/article/details/73498692 加密算法: 1.单项加密 2.对称加密 3.非对称加密 简单 ...
- python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解
python中"生成器"."迭代器"."闭包"."装饰器"的深入理解 一.生成器 1.生成器定义:在python中,一边 ...
- NET Core 2.1 Preview 1
NET Core 2.1 Preview 1 [翻译] .NET Core 2.1 Preview 1 发布 原文: Announcing .NET Core 2.1 Preview 1 今天,我们宣 ...
- jquery的$().each和$.each的区别
在jquery中,遍历对象和数组,经常会用到$().each和$.each(),两个方法.两个方法是有区别的,从而这两个方法在针对不同的操作上,显示了各自的特点. $().each,对于这个方法,在d ...
- ImageLoader常用方法注释
ImageLoader中的常用方法及相关作用注释 ImageLoader 的ImageLoaderConfiguration config 配置 ImageLoaderConfiguration co ...