【树链剖分 ODT】cf1137F. Matches Are Not a Child's Play
孔爷的杂题系列;LCT清新题/ODT模板题
题目大意

定义一颗无根树的燃烧序列为:每次选取编号最小的叶子节点形成的序列。
要求支持操作:查询一个点$u$在燃烧序列中的排名;将一个点的编号变成最大
$n \le 200000$
题目分析
首先初始的燃烧序列容易构造,那么考虑进行一次up操作对序列会产生什么影响。

这里对$3$进行一次$up$,得到下图。

容易发现,记上一个版本序列最后一个元素为$las$,进行$up\,\,\,x$相当于是把路径$(las,x)$的答案变成从$las$到$x$的等差数列。因为$x$被$up$之后,这条路径只能从另一端的$las$走过来。

等差数列用线段树容易维护,这里讲一种ODT维护的方式:将路径$(las,x)$染为一种新颜色$c$,查询答案就是$1..c-1$颜色种类数+$dis(las,x)+1$.
那么就是一道难得的ODT+树剖模板题了。
关于下面132行的细节处理:写成root[i-1]=root[i]=u是因为对于初始序列,查询时候要保持dist(u, root[c-1])=0;但是对于之后修改的询问root[n]应该为n。
#include<bits/stdc++.h>
const int maxn = ;
const int maxm = ; struct node
{
int l,r,val;
node(int a=, int b=, int c=):l(a),r(b),val(c) {}
bool operator < (node a) const
{
return l < a.l;
}
};
struct point
{
int fa,son,top,tot;
}a[maxn];
char opt[];
int n,m,tim,lst,chain[maxn],chTot,root[maxn<<];
int edgeTot,head[maxn],nxt[maxm],edges[maxm],deg[maxn],dep[maxn];
std::set<node> s[maxn];
std::priority_queue<int, std::vector<int>, std::greater<int> > q;
typedef std::set<node>::iterator itr;
namespace BIT
{
int f[maxn<<];
void add(int x, int c){for (x+=; x<=n+m+; x+=x&-x) f[x] += c;}
int query(int x)
{
int ret = ;
for (x+=; x; x-=x&-x) ret += f[x];
return ret;
}
}; 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)
{
++deg[u], ++deg[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)
{
a[x].fa = fa, a[x].tot = ;
a[x].son = a[x].top = -, dep[x] = dep[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)
{
if (x==top) s[x].insert(node(n+, n+, ));
chain[x] = ++chTot, a[x].top = top;
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]);
}
int Lca(int u, int v)
{
while (a[u].top!=a[v].top)
{
if (dep[a[u].top] > dep[a[v].top]) std::swap(u, v);
v = a[a[v].top].fa;
}
if (dep[u] > dep[v]) std::swap(u, v);
return u;
}
int dist(int u, int v)
{
int anc = Lca(u, v);
return dep[u]+dep[v]-(dep[anc]<<);
}
itr split(int i, int pos)
{
itr loc = s[i].lower_bound(node(pos));
if (loc!=s[i].end()&&loc->l==pos) return loc;
int l = (--loc)->l, r = loc->r, val = loc->val;
s[i].erase(loc), s[i].insert(node(l, pos-, val));
return s[i].insert(node(pos, r, val)).first;
}
void insert(int i, int l, int r, int c)
{
itr rpos = split(i, r+), lpos = split(i, l);
for (itr it=lpos; it!=rpos; ++it)
BIT::add(it->val, -(it->r-it->l+)); //遍历清除历史颜色
s[i].erase(lpos, rpos);
BIT::add(c, r-l+);
s[i].insert(node(l, r, c));
}
void chainModify(int u, int v)
{
while (a[u].top!=a[v].top)
{
if (dep[a[u].top] > dep[a[v].top]) std::swap(u, v);
insert(a[v].top, chain[a[v].top], chain[v], tim);
v = a[a[v].top].fa;
}
if (dep[u] > dep[v]) std::swap(u, v);
insert(a[u].top, chain[u], chain[v], tim);
}
int query(int u)
{
int c = split(a[u].top, chain[u])->val;
return BIT::query(c-)+dist(u, root[c-])+; //查询答案 root[c-1]是指上一个历史版本的最后一个元素las
}
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<=n; i++)
if (deg[i]==) q.push(i);
for (int i=,u; i<=n; i++)
{
root[i-] = root[i] = u = q.top(), q.pop(); //见上解释
BIT::add(i, ), deg[u] = ;
s[a[u].top].insert(node(chain[u], chain[u], ++tim));
for (int i=head[u]; i!=-; i=nxt[i])
if ((--deg[edges[i]])==) q.push(edges[i]);
}
for (int i=; i<=m; i++)
{
scanf("%s",opt);
if (opt[]=='u'){
int v = read();
root[++tim] = v;
chainModify(v, root[tim-]);
}else if (opt[]=='w') printf("%d\n",query(read()));
else{
int u = read(), v = read();
printf("%d\n",(query(u) < query(v))?u:v);
}
}
return ;
}
END
【树链剖分 ODT】cf1137F. Matches Are Not a Child's Play的更多相关文章
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- codevs 1228 苹果树 树链剖分讲解
题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...
- 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)
题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...
- 树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)
题目链接 题意: 有n个点的一棵树,两种操作: 1. a到b的路径上,给一个y,对于路径上每一条边,进行操作,问最后的y: 2. 修改某个条边p的值为c 思路: 链上操作的问题,想树链剖分和LCT,对 ...
- 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)
题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...
- bzoj2243树链剖分+染色段数
终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...
- bzoj3631树链剖分
虽然是水题1A的感觉太爽了O(∩_∩)O~ 题意相当于n-1次树上路径上每个点权值+1,最后问每个点的权值 本来想写线段树,写好了change打算框架打完了再来补,结果打完发现只是区间加和单点查 前缀 ...
- BZOJ 3531: [Sdoi2014]旅行 [树链剖分]
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1685 Solved: 751[Submit][Status] ...
随机推荐
- socket编程(一)
因为下载器涉及到socket的知识,就花了一天学习了.因为时间原因分成几部分.(这里记录上的是基于Windows平台的) #include <stdio.h> #include <w ...
- SQL内外连接的区别
项目当中,需要将SQL server中的部分数据导入mongo中,由于SQL是关系型数据库的原因,需要联合多表进行查询,因此,了解了下SQL中内外连接的相关概念,以作备注: 1.内联接(典型的联接运算 ...
- C#继承 多态
1.继承 允许我们根据一个类来定义另一个类.已有的类被称为的基类(父类),新的类被称为派生类(子类). 单一继承:只能有一个基类,一个基类可以派生出多个派生类,一个类别只可以继承自一个父类. 多重继承 ...
- 搭建maven web项目并配置quartz定时任务【业务:对比数据变化内容】 历程
搭建maven web项目并配置quartz定时任务[业务:对比数据变化内容] 历程2018年03月03日 10:51:10 守望dfdfdf 阅读数:100更多个人分类: 工作 问题编辑版权声明:本 ...
- Hibernate课程 初探多对多映射2-4 测试
package com.ddwei.test; import org.hibernate.Session; import org.hibernate.Transaction; import com.d ...
- Hibernate课程 初探多对多映射2-2 创建持久化类和映射文件
生成实体类 和 cfg.xml配置 cfg.xml 参照一对多映射 实体类如下: Project 类 package com.ddwei.entity; import java.util.HashSe ...
- due to a StackOverflowError. Possible root causes include a too low。。
我们可以用另外的办法来解决这个问题,我们让tomcat不扫描指定的jar包,tomcat就要轻松得多了,org.apache.tomcat.util.scan.StandardJarScanner中定 ...
- 数据仓库是什么?OLTP和OLAP是什么?
数据仓库(Data Warehouse)是一个面向主题的(Subject Oriented).集成的(Integrate).相对稳定的(Non-Volatile).反映历史变化(Time Varian ...
- Linux文件种类与扩展名
一.文件种类 1)普通文件:ls -al第一个字符为[-]的 纯文本文件(ASCII) 二进制文件(binary):Linux中的可执行文件 数据格式文件(data):特定格式的文件,如:Linux登 ...
- RC4 in TLS is Broken: Now What?
https://community.qualys.com/blogs/securitylabs/2013/03/19/rc4-in-tls-is-broken-now-what RC4 has lon ...