【树链剖分 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] ...
随机推荐
- 安装rails遇到的问题
1 要安装js运行环境,例如Nodejs,如果使用nvm记得,安装完执行nvm use '版本号' 2 或者在Gemfile文件中加入: gem 'execjs'gem 'therubyracer'然 ...
- Android串口操作,简化android-serialport-api的demo(转载)
原帖地址:点击打开 最近在做android串口的开发,找到一个开源的串口类android-serialport-api.其主页在这里http://code.google.com/p/android-s ...
- js随堂初体验(一)
Js初体验(-) 1 js的基础知识 A web三大标准:1 html:结构标准 2 css:表现标准 3 javascript:行为标准 B js三种书写方式:1 行内js:onclick ...
- 工作中遇到的vscode配合eslint完成保存为eslint格式
vscode个人设置 // vscode的个人设置配置 { "workbench.iconTheme": "vscode-icons", "workb ...
- WHRER条件里的数据类型必须和字段数据类型一致
首先看案例: 表中字段FPHONE_IMEI是varchar类型的,主键也建立在FPHONE_IMEI 字段上,原则上只要where条件中用到了这个字段,就会走索引,这也是建立索引的目的,可事实是这样 ...
- HBuilder中改造console.info
HBuilder的js中console.info只会输出头一个参数,与谷歌浏览器行为不符合.让人很不习惯. 于是,对其改造一番. window.console.print=window.console ...
- ListView优化的时候ViewHolder的简洁写法
在ListVIew做复用优化的时候,经常会写ViewHolder,还需要很麻烦的去findview,我最讨厌写一堆的这样代码了,今天看到了一个极简的写法,很好用,很简洁啊!!! public stat ...
- 【起航计划 018】2015 起航计划 Android APIDemo的魔鬼步伐 17 App->Alarm->Alarm Service
Alarm Service和Alarm Controller 例子非常类似,只是Alarm Service是用来Schedule一个Service,而前面的例子是来Schedule一个Broadcas ...
- EF--Model First
Model First先设计Model对象,再由对象生成数据库. 1.新建控制台项目,名称ModelFirst,确定. 2.点击选中项目,右键-->添加-->新建项目--选择数据模板--& ...
- Struts2_中文问题
1.如果有中文,表单提交就用POST方式,别用GET方式. 2.配置 <constant name="struts.i18n.encoding" value="UT ...