已经连咕了好几天博客了;比较经典的题目

题目大意

给出一个 N 个点的树和$K_i$, 求每个点到其他所有点距离中第 $K_i$ 小的数值。

题目分析

做法一:点分树上$\log^3$

首先暴力做法:对于每个节点维护其他点距离的值域线段树。这个做法的瓶颈在于关于边$(u,v)$线段树的转移。那么可以利用点分树(为了保证复杂度)换一种容斥的思路利用重复的信息:记$f_i$为以$i$为根的点分树内所有其他点到点$i$的距离的值域线段树;$g_i$为以$i$为根的点分树内,所有点到$i$的点分树父亲的距离 的值域线段树。

询问的时候,记$LIM$为二分的长度,查询点为$pos$,$lst$的点分树父亲为$i$,那么每一层的贡献就是$f_i$中$LIM-dis(pos,i)$减去$g_{lst}$中$LIM-dis(pos,i)$的代价,注意还要特判一下$(pos,i)$这条路径是否会被算入贡献。

 #include<bits/stdc++.h>
const int maxLog = ;
const int maxn = ;
const int maxm = ;
const int maxNode = ; struct node
{
int l,r,val;
};
int LIM;
struct RangeSeg
{
int tot,rt[maxn];
node a[maxNode];
void modify(int &rt, int l, int r, int pos)
{
if (!rt) rt = ++tot;
++a[rt].val;
if (l==r) return;
int mid = (l+r)>>;
if (pos <= mid) modify(a[rt].l, l, mid, pos);
else modify(a[rt].r, mid+, r, pos);
}
int query(int rt, int L, int R, int l, int r)
{
if (!rt) return ;
if (L <= l&&r <= R) return a[rt].val;
int mid = (l+r)>>, ret = ;
if (L <= mid) ret = query(a[rt].l, L, R, l, mid);
if (R > mid) ret += query(a[rt].r, L, R, mid+, r);
return ret;
}
void modify(int x, int c)
{
modify(rt[x], , LIM, c);
}
int query(int x, int l, int r)
{
if (l <= r) return query(rt[x], l, r, , LIM);
else return ;
}
}f,g;
int n,k[maxn];
int dep[maxn],fat[maxn][maxLog],lay[maxn];
int size[maxn],bloTot,son[maxn],root;
int edgeTot,head[maxn],nxt[maxm],edges[maxm];
bool vis[maxn]; 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)
{
edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
}
int lca(int x, int y)
{
if (dep[x] > dep[y]) std::swap(x, y);
for (int i=; i>=; i--)
if (dep[fat[y][i]] >= dep[x]) y = fat[y][i];
if (x==y) return x;
for (int i=; i>=; i--)
if (fat[x][i]!=fat[y][i]) x = fat[x][i], y = fat[y][i];
return fat[x][];
}
int dist(int x, int y){return dep[x]+dep[y]-(dep[lca(x, y)]<<);}
void dfs(int x, int fa)
{
fat[x][] = fa, dep[x] = dep[fa]+;
for (int i=; i<=; i++)
fat[x][i] = fat[fat[x][i-]][i-];
for (int i=head[x]; i!=-; i=nxt[i])
if (edges[i]!=fa) dfs(edges[i], x);
}
void getRoot(int x, int fa)
{
size[x] = , son[x] = ;
for (int i=head[x]; i!=-; i=nxt[i])
{
int v = edges[i];
if (v==fa||vis[v]) continue;
getRoot(v, x);
size[x] += size[v];
son[x] = std::max(son[x], size[v]);
}
son[x] = std::max(son[x], bloTot-size[x]);
if (son[x] < son[root]) root = x;
}
void color(int Top, int x, int fa)
{
if (Top!=x) f.modify(Top, dist(Top, x));
if (lay[Top]) g.modify(Top, dist(lay[Top], x));
for (int i=head[x]; i!=-; i=nxt[i])
if (edges[i]!=fa&&!vis[edges[i]]) color(Top, edges[i], x);
}
void deal(int x, int pre)
{
lay[x] = pre, color(x, x, x), vis[x] = true;
for (int i=head[x]; i!=-; i=nxt[i])
{
int v = edges[i];
if (vis[v]) continue;
bloTot = size[v], root = , getRoot(v, );
deal(root, x);
}
}
int count(int x, int num)
{
int ret = f.query(x, , num);
for (int i=lay[x],lst=x; i; lst=i,i=lay[i])
{
int d = dist(x, i);
if (d <= num) ++ret, ret += f.query(i, , num-d)-g.query(lst, , num-d);
}
return ret;
}
int main()
{
memset(head, -, sizeof head);
LIM = n = read();
for (int i=; i<=n; i++) k[i] = n-read();
for (int i=; i<n; i++) addedge(read(), read());
dfs(, );
bloTot = n, root = , son[] = n, getRoot(, );
deal(root, );
for (int i=; i<=n; i++)
{
int L = , R = LIM, ans = ;
for (int mid=(L+R)>>; L<=R; mid=(L+R)>>)
if (count(i, mid) < k[i]) L = mid+, ans = mid;
else R = mid-;
printf("%d ",ans);
}
return ;
}

做法二:序列问题分块

不说了。类似的套路见#6046. 「雅礼集训 2017 Day8」爷

【点分树】codechef Yet Another Tree Problem的更多相关文章

  1. BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)

    题目描述 Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的 ...

  2. BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】

    A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...

  3. Codechef Observing the Tree

    Home » Practice(Hard) » Observing the Tree   https://www.codechef.com/problems/QUERY Observing the T ...

  4. 动态树之LCT(link-cut tree)讲解

    动态树是一类要求维护森林的连通性的题的总称,这类问题要求维护某个点到根的某些数据,支持树的切分,合并,以及对子树的某些操作.其中解决这一问题的某些简化版(不包括对子树的操作)的基础数据结构就是LCT( ...

  5. 一篇自己都看不懂的点分治&点分树学习笔记

    淀粉质点分治可真是个好东西 Part A.点分治 众所周知,树上分治算法有$3$种:点分治.边分治.链分治(最后一个似乎就是树链剖分),它们名字的不同是由于分治方式的不同的.点分治,顾名思义,每一次选 ...

  6. 【学习笔记 边分树】【uoj400】【CTSC2018】暴力写挂

    题目 描述 ​ 有两棵树\(T\)和\(T'\),节点个数都为\(n\),根节点都为\(1\)号节点; ​ 求两两点之间 $$ \begin{align} depth(x) + depth(y) - ...

  7. cdqz2017-test8-Tree(点分树)

    n个点的带点权带边权的树,设点权为a[i],边权为b[i] 一棵树有n*(n-1)/2个点对, 定义这棵树的价值为任意两点对的(a[x]^a[y])*dis(x,y) 有m次修改一个点的点权的操作 输 ...

  8. 2018.08.28 洛谷P3345 [ZJOI2015]幻想乡战略游戏(点分树)

    传送门 题目就是要求维护带权重心. 因此破题的关键点自然就是带权重心的性质. 这时发现直接找带权重心是O(n)的,考虑优化方案. 发现点分树的树高是logn级别的,并且对于以u为根的树,带权重心要么就 ...

  9. Codechef Union on Tree

    Codechef Union on Tree https://www.codechef.com/problems/BTREE 简要题意: 给你一棵树,\(Q\)次询问,每次给出一个点集和每个点的\(r ...

随机推荐

  1. HTTP的一些理解

    URI是Uniform Resource Identifier的缩写,统一资源标识符.URI用字符串标识某一互联网资源,而URL标识资源的地点(互联网上所处的位置).可见URL是URI的子集. 典型的 ...

  2. 基于Python Selenium Unittest PO设计模式详解

    本文章会讲述以下几个内容: 1.什么是PO设计模式(Page Object Model) 2.为什么要使用PO设计模式 3.使用PO设计模式要点 4.PO设计模式实例 1.什么是PO设计模式 (Pag ...

  3. hive与hbase关联

    进入hbase: hbase shell 进入HIVE: hive hbase中建一张t_student_info表,添加两个列族 create 't_student_info','st1','st2 ...

  4. 021 Merge Two Sorted Lists 合并两个有序链表

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  5. IE浏览器与非IE浏览器JS日期兼容性问题处理

    执行语句 console.log(new Date("2017-07-04 18:40").getTime()); 在IE浏览器中打印出:NAN 在非IE浏览器中打印出:14991 ...

  6. UiPath Studio 快捷键

    掌握快捷键可以事半功倍,写一下比较重要的 1. Ctrl + J  插入代码片段 2. Ctrl + K  快速建变量 3. Ctrl + L  打开日志文件夹 4. Ctrl + F4  关闭当前机 ...

  7. Teradata 认证系列 - 3. 关系型数据库的概念

    本课的学习目标 定义关系型数据库关联的术语 讨论主键的功能 讨论外键的功能 列出关系型数据库的优势 描述星型架构和第三范式数据模型的区别 什么是数据库?数据库是一个应用永久保存数据的集合表现在: 逻辑 ...

  8. BZOJ3693: 圆桌会议(Hall定理 线段树)

    题意 题目链接 Sol 好的又是神仙题... 我的思路:对于区间分两种情况讨论,一种是完全包含,另一种是部分包含.第一种情况非常好判断,至于计算对于一个区间[l, r]的$\sum a[i]$就可以了 ...

  9. 【web】movie review——静态页面训练、css训练

    实现样式要求: image: banner.png: generaloverview.png: background.png: bannerbackground.png: rottenbig.png: ...

  10. 用C#来控制高级安全Windows防火墙

    有的时候我们需要在自己的产品中检测<高级安全Windows防火墙>的状态,并有可能需要加入一些规则甚至需要关闭掉高级安全Windows防火墙. 下面就告诉如何来做: <高级安全Win ...