[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 ...
随机推荐
- 关于spring cloud “Finchley.RC2”版本在spring cloud config中的ArrayIndexOutOfBoundsException
原文 https://www.cnblogs.com/Little-tree/p/9166382.html 在学spring cloud config的时候遇到一个ArrayIndexOutOfBou ...
- 二、CI框架之MCV模型
一.关于MCV,大概就是下图所示: 模型(model)-视图(view)-控制器(controller) M用来处理数据库,V用来显示界面,C用来控制 二.对应到CI的源码,对应的是这3个目录 不忘初 ...
- 美素数(HDU 4548)(打表,简化时间复杂度)
相信大家都喜欢美的东西,让我们一起来看看美素数吧. 问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为"美素数",如29,本身是素数,而且2+9 = 11 ...
- 自己整理的常用SQL Server 2005 语句、
--创建数据库 create database 数据库 go --打开数据库 use 数据库 --删除数据库 drop database 数据库 Go --创建数据表 create table 数据表 ...
- HDU - 1068 Girls and Boys(二分匹配---最大独立集)
题意:给出每个学生的标号及与其有缘分成为情侣的人的标号,求一个最大集合,集合中任意两个人都没有缘分成为情侣. 分析: 1.若两人有缘分,则可以连一条边,本题是求一个最大集合,集合中任意两点都不相连,即 ...
- Ubuntu16.04 faster-rcnn+caffe+gpu运行环境配置以及解决各种bug
https://blog.csdn.net/flygeda/article/details/78638824 本文主要是对近期参考的网上各位大神的博客的总结,其中,从安装系统到跑通程序过程中遇到的各种 ...
- caffe中运行mnist
mnist样本字库嘚图片转换:# coding=utf-8import numpy as npimport struct import matplotlib.pyplot as plt from PI ...
- go 的参数传递
再go语言中没有引用传递,所有都是按照值拷贝的方式传递的. 数组:实际就是堆栈上的一段连续内存,和c类似.(可以更加反编译代码推断 go tool compile -S main.go > ma ...
- android studio 黑屏问题
AVD配置不对,打开AVD从新配置
- Python-查找并保存特定字符串后面的字符串
-- -- 本算法用于查找并存储“特定字符串”后面的字符串. -- 举例: strli = "kaka is li is da is wei !" #用于查找的字符串 sep_li ...