[ZJOI2019]语言(树链剖分+动态开点线段树+启发式合并)
首先,对于从每个点出发的路径,答案一定是过这个点的路径所覆盖的点数。然后可以做树上差分,对每个点记录路径产生总贡献,然后做一个树剖维护,对每个点维护一个动态开点线段树。最后再从根节点开始做一遍dfs,把每个节点对应的线段树启发式合并即可。时空复杂度均为O(nlog2n)。听说还有一个log的做法,但感觉太神仙不会,不过2个log能过就不管了。
#include<bits/stdc++.h>
#define lson l,mid,tr[rt].lc
#define rson mid+1,r,tr[rt].rc
using namespace std;
const int N=1e5+;
struct Seg{int lc,rc,tag,sz;}tr[N*];
int n,m,cnt,fa[N],sz[N],dep[N],son[N],top[N],dfn[N],rt[N];
long long ans;
vector<int>G[N];
void dfs1(int u,int f)
{
sz[u]=,dep[u]=dep[f]+,fa[u]=f;
for(int i=;i<G[u].size();i++)
if(G[u][i]!=f)
{
dfs1(G[u][i],u),sz[u]+=sz[G[u][i]];
if(sz[son[u]]<sz[G[u][i]])son[u]=G[u][i];
}
}
void dfs2(int u,int tp)
{
top[u]=tp,dfn[u]=++cnt;
if(son[u])dfs2(son[u],tp);
for(int i=;i<G[u].size();i++)if(G[u][i]!=fa[u]&&G[u][i]!=son[u])dfs2(G[u][i],G[u][i]);
}
void pushup(int rt,int len)
{if(tr[rt].tag)tr[rt].sz=len;else tr[rt].sz=tr[tr[rt].lc].sz+tr[tr[rt].rc].sz;}
void modify(int rt,int v,int len){tr[rt].tag+=v;pushup(rt,len);}
void update(int L,int R,int v,int l,int r,int&rt)
{
if(!rt)rt=++cnt;
if(L<=l&&r<=R){modify(rt,v,r-l+);return;}
int mid=l+r>>;
if(L<=mid)update(L,R,v,lson);
if(R>mid)update(L,R,v,rson);
pushup(rt,r-l+);
}
void Update(int&rt,int x,int y,int v)
{
while(top[x]!=top[y])update(dfn[top[x]],dfn[x],v,,n,rt),x=fa[top[x]];
if(x!=y)update(dfn[y]+,dfn[x],v,,n,rt);
}
int lca(int x,int y)
{
while(top[x]!=top[y])if(dep[top[x]]<dep[top[y]])y=fa[top[y]];else x=fa[top[x]];
return dep[x]<dep[y]?x:y;
}
int merge(int u,int v,int l,int r)
{
if(!u||!v)return u+v;
tr[u].tag+=tr[v].tag;
if(l==r){pushup(u,);return u;}
int mid=l+r>>;
tr[u].lc=merge(tr[u].lc,tr[v].lc,l,mid);
tr[u].rc=merge(tr[u].rc,tr[v].rc,mid+,r);
pushup(u,r-l+);
return u;
}
void dfs3(int u,int f)
{
for(int i=;i<G[u].size();i++)
if(G[u][i]!=f)dfs3(G[u][i],u),rt[u]=merge(rt[u],rt[G[u][i]],,n);
ans+=max(tr[rt[u]].sz-,);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x,y;i<n;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x);
dfs1(,);
dfs2(,);
cnt=;
for(int i=,x,y,f;i<=m;i++)
{
scanf("%d%d",&x,&y);
f=lca(x,y);
Update(rt[x],x,fa[f],),Update(rt[x],y,f,);
Update(rt[y],x,fa[f],),Update(rt[y],y,f,);
Update(rt[f],x,fa[f],-),Update(rt[f],y,f,-);
if(fa[f])Update(rt[fa[f]],x,fa[f],-),Update(rt[fa[f]],y,f,-);
}
dfs3(,);
cout<<ans/;
}
[ZJOI2019]语言(树链剖分+动态开点线段树+启发式合并)的更多相关文章
- 【bzoj4999】This Problem Is Too Simple! 树链剖分+动态开点线段树
题目描述 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) ...
- [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
- BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树
题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...
- bzoj3531: [Sdoi2014]旅行 (树链剖分 && 动态开点线段树)
感觉动态开点线段树空间复杂度好优秀呀 树剖裸题 把每个宗教都开一颗线段树就可以了 但是我一直TLE 然后调了一个小时 为什么呢 因为我 #define max(x, y) (x > y ? x ...
- 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树
[BZOJ3531][Sdoi2014]旅行 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天 ...
- BZOJ4999: This Problem Is Too Simple!树链剖分+动态开点线段树
题目大意:将某个节点的颜色变为x,查询i,j路径上多少个颜色为x的点... 其实最开始一看就是主席树+树状数组+DFS序...但是过不去...MLE+TLE BY FCWWW 其实树剖裸的一批...只 ...
- bzoj3531——树链剖分+动态开点线段树
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MB Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连 ...
- [LuoguU41039]PION后缀自动机 树链剖分+动态开点线段树
链接 刚开始看出题人题解都吓蒙掉了,还以为是什么难题,结果就一板子题 思路:对每一个文件名开一棵线段树,然后树剖即可 #include<bits/stdc++.h> #define REP ...
随机推荐
- 第二阶段scrum-2
1.整个团队的任务量: 2.任务看板: 会议照片: 产品状态: 正在连接配置数据库部分
- mybatis的一对多和多对一的连接查询
实体类: package com.entity; import java.util.List; public class Dept { private Integer deptId; private ...
- jQuery选择器全解析
1. 基本选择器 1.1 id选择器:$(#id) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...
- ORACLE常见问题收集
1.Java代码执行oracle,update和insert语句卡住不动 解决方法:造成这样的情况原因在于你之前执行了update或insert操作但你并没有commit,导致你操作的这条记录被ora ...
- c++ 排序 冒泡 插入 选择 快速
//冒泡 #include <iostream> using namespace std; void bubbleSort(int* list,int index) { ;i--) //i ...
- JS高级学习笔记(2)之js多线程
参考大神:Javascript多线程 web worker ---- 6.Web Worker 概述 截图过来: 线程之间的通信 let worker = new Worker(‘js文件路径’) 主 ...
- 再谈记忆化搜索 HDU-1078
最近做DP题目,发现无论是LCS,还是有些题目涉及将动态规划的路径打印出来,而且有时候还要按格式输出,这个时候,记忆化搜索显得尤其重要,确实,记忆化搜索使用优化版本的动态规划,用起来思路清晰,非常方便 ...
- apache安装和mysql php配置问题
apache下载和安装: 下载网址:http://httpd.apache.org/ 然后 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~ ...
- nginx常用编译参数
./configurate --prefix=/app/tengine --user=www --group=www --with-http_v2_module --with-http_ssl_mod ...
- h5-FileReader对象的使用
<!--FileReader对象的使用--> <!--需要及时预览 及时:当用户选择完图片之后就立即进行预览处理--onchange事件 预览:通过文件读取对象的readAsData ...