【树链剖分 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] ...
随机推荐
- 关于.Net WebAPI数据认证(包括登陆认证、模型认证)
1.登陆认证使用WebAPI自动认证 webApi自动认证继承类:AuthorizeAttribute 自动认证类使用在控制器上 [Authentication] public class Card ...
- Hibernate系列4-----之删除
1.和它的增改查兄弟不同,多了个until包定义了HibernateUntil类,让我们来一起看看吧 public class HibernateUntil { private static Conf ...
- guava的重试机制guava-retrying使用
1,添加maven依赖 <dependency> <groupId>com.github.rholder</groupId> <artifactId>g ...
- node-sass 安装报错解决办法
npm install安装node-sass时出现以下问题: Cannot download https://github.com/sass/node-sass/releases/download/v ...
- HTTP杂记
HTTP请求中的浏览器Timing信息: stalled:浏览器发出请求到这个请求可以发出的等待时间 proxy negotiation: 代理协商的时间 request sent:请求的第一个字节发 ...
- sharepoint2007就地升级2010系列(四)升级数据库
上一篇我们完成了系统的升级,今天我们来看一下SQL2005X64是如何升级到SQL2008X64的. 首先,我们先停掉所有sharepoint的服务 其实网上的文档并没有写到这一步,但是我个人觉得,要 ...
- Java Knowledge series 3
JVM & Bytecode Abstract & Object Object in Java (1) 所有东西都是对象object.可将对象想象成一种新型变量:它保存着数据,但可要求 ...
- adb使用wifi无线连接调试Android设备
先上官方原文: Wireless usage adb is usually used over USB. However, it is also possible to use over Wi-Fi, ...
- nginx启动时报错
nginx启动时报错 原因:nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed /var/cache/ngin ...
- Spring Boot项目Circular view path问题解决
使用Spring Boot创建Spring MVC项目,访问url请求出现问题:Circular view path 1.问题描述 控制台打印: javax.servlet.ServletExcept ...