孔爷的杂题系列;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的更多相关文章

  1. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  2. BZOJ 1984: 月下“毛景树” [树链剖分 边权]

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1728  Solved: 531[Submit][Status][Discu ...

  3. codevs 1228 苹果树 树链剖分讲解

    题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...

  4. 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)

    题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...

  5. 树链剖分+线段树 CF 593D Happy Tree Party(快乐树聚会)

    题目链接 题意: 有n个点的一棵树,两种操作: 1. a到b的路径上,给一个y,对于路径上每一条边,进行操作,问最后的y: 2. 修改某个条边p的值为c 思路: 链上操作的问题,想树链剖分和LCT,对 ...

  6. 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)

    题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...

  7. bzoj2243树链剖分+染色段数

    终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...

  8. bzoj3631树链剖分

    虽然是水题1A的感觉太爽了O(∩_∩)O~ 题意相当于n-1次树上路径上每个点权值+1,最后问每个点的权值 本来想写线段树,写好了change打算框架打完了再来补,结果打完发现只是区间加和单点查 前缀 ...

  9. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

随机推荐

  1. 转:Android开源项目推荐之「网络请求哪家强」 Android开源项目推荐之「网络请求哪家强」

    转载自https://zhuanlan.zhihu.com/p/21879931 1. 原则 本篇说的网络请求专指 http 请求,在选择一个框架之前,我个人有个习惯,就是我喜欢选择专注的库,其实在软 ...

  2. Sublime Text格式化HTML JS CSS代码

    Sublime Text是开发Hybrid应用的神器,但是有时候对糟糕的代码格式很懊恼,尤其是团队成员比较多,并且代码风格不是很统一的时候.幸好有可用的格式化插件,比较好用的就是HTML-CSS-JS ...

  3. node搭环境

    node是javascript的运行环境,npm是nodejs的包管理器,用于node插件管理(包括安装.卸载.管理依赖等). 一.安装node 1.在https://nodejs.org/en/do ...

  4. jQuery Validate验证框架详解(转)

    jQuery校验官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation 一.导入js库 <script type=& ...

  5. iOS-swift-类和对象

    1.类(class) 使用关键字 class 创建一个类.属性直接在类里面声明,属性可以是变量,也可以是常量.方法和函数的创建方法一致. class Shape { var numberOfSides ...

  6. JavaScript 对象继承 OOP (三)

      对象继承 A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. JavaScript 语言的继承不通过 class (es6 中的class 不过是 ...

  7. css 两大特性:继承性和层叠性

    css 有两大特性: 继承性和层叠性, 继承性 面向对象语言都会存在继承的概念,在面向对象的语言中,继承的特点:继承了父类的属性和方法.那么我们现在主要研究css,css中没有方法,所以我们仅仅继承属 ...

  8. cube.js 开源模块化分析框架

    cube.js 是一款很不错的模块化web 应用分析框架.cube.js 的设计主要是面向serverless 服务, 但是同时也支持所有rdbms, cube.js不是一个单体应用,包含了以下部分: ...

  9. Redis 基础概念和命令

    Redis 是什么 Redis是一种基于键值对(key-value)的NoSQL数据库. 为什么使用Redis 速度快 Redis的时间颗粒度一般是微秒,慢查询的默认值是10 000微秒,即10毫秒. ...

  10. AFNetworking 使用总结 (用法+JSON解析

    AFNetwork是一个轻量级的网络请求api类库.是以NSURLConnection, NSOperation和其他方法为基础的. 下面这个例子是用来处理json请求的: NSURL *url =  ...