传送门

题解:
设一个阀值 k k k,小于 k k k的倍增,大于 k k k的暴力跳,这样的复杂度是 O ( n m k + n k ) O(\frac{nm}{k}+nk) O(knm​+nk)的,取 k = m k=\sqrt{m} k=m ​最优,时间复杂度为 O ( n m ) O(n \sqrt{m}) O(nm ​)。不过空间开不下,要开小一点。

同时有个结论:我们可以从两端跳到lca,最后拼起来,这样就大大降低代码复杂度了。

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;const int RLEN=1<<18|1;
inline char nc() {static char ibuf[RLEN],*ib,*ob;(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));return (ib==ob) ? -1 : *ib++;
}
inline int rd() {char ch=nc(); int i=0,f=1;while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}return i*f;
}const int N=1e5+50, S=100, L=18;int n,m,id[N],tot;
namespace ori_tree {int fa[N][L+1],val[N],dep[N],d[N];vector <pii> e[N];inline int lca(int x,int y) {if(d[x]<d[y]) swap(x,y);int u=d[x]-d[y];for(int i=0;i<=L;i++) if((u>>i)&1) x=fa[x][i];if(x==y) return x;for(int i=L;i>=0;i--) if(fa[x][i]^fa[y][i]) x=fa[x][i], y=fa[y][i];return fa[x][0];}inline void dfs_pre(int x,int f) {id[x]=++tot; for(auto v:e[x]) if(v.first^f)dfs_pre(v.first,x);}inline void dfs(int x,int f) {fa[x][0]=f; dep[x]=dep[f]+val[x]; d[x]=d[f]+1;for(int i=1;i<=L;i++) fa[x][i]=fa[fa[x][i-1]][i-1];for(auto v:e[x]) if(v.first^f) val[v.first]=v.second, dfs(v.first,x);}inline void init() {n=rd();vector <pair<int,pair<int,int>> > vec;for(int i=1;i<n;i++) {int x=rd(), y=rd(), w=rd();e[x].push_back(pii(y,w));e[y].push_back(pii(x,w));vec.push_back(make_pair(w,pii(x,y)));} dfs_pre(1,0);for(int i=1;i<=n;i++) e[i].clear();for(auto i:vec) {int x=id[i.second.first], y=id[i.second.second], w=i.first;e[x].push_back(pii(y,w));e[y].push_back(pii(x,w));} dfs(1,0);}
}
using ori_tree::dep;
using ori_tree::val;struct Tree {int fa[N],top[N],d[N];int sze[N],son[N];vector <int> chain[N];vector <int> e[N];inline void dfs(int x,int f) {sze[x]=1; d[x]=d[f]+1;for(auto v:e[x]) {dfs(v,x); sze[x]+=sze[v];if(sze[v]>=sze[son[x]]) son[x]=v;}}inline void dfs_top(int x) {chain[top[x]].push_back(x);for(auto v:e[x]) {top[v]=(son[x]==v) ? top[x] : v;dfs_top(v);}}inline void init() {for(int i=2;i<=n;i++) if(fa[i] && fa[i]!=i) e[fa[i]].push_back(i);for(int i=1;i<=n;i++) if(!top[i])dfs(i,0), top[i]=i, dfs_top(i);}inline pii group(int x,int f) {int cnt=0;while(fa[top[x]] && dep[fa[top[x]]]>dep[f]) cnt+=d[x]-d[fa[top[x]]], x=fa[top[x]];int l=0, r=d[x]-d[top[x]];while(l<=r) {int mid=(l+r)>>1, u=chain[top[x]][mid];if(dep[u]>dep[f]) {cnt+=d[x]-d[u];x=u; r=mid-1;} else l=mid+1;} return pii(cnt,dep[x]-dep[f]);}
} tr[S+1];
inline void dfs_pre(int x,int f) {for(int i=0;i<=S;i++) {if(i<val[x]) tr[i].fa[x]=x;else tr[i].fa[x]=tr[i-val[x]].fa[f];}for(auto v:ori_tree::e[x]) if(v.first^f) dfs_pre(v.first,x);
}
inline pii group(int x,int f,int step) {if(step<=S) {return tr[step].group(x,f);} else {int cnt=0;while(dep[x]-dep[f]>=step) {int l=x;while(l!=f && tr[S].fa[l]!=l && dep[x]-dep[tr[S].fa[l]]<=step) l=tr[S].fa[l];int res=step-(dep[x]-dep[l]);  l=tr[res].fa[l];++cnt; x=l;}return pii(cnt,dep[x]-dep[f]);}
}
int main() {ori_tree::init();dfs_pre(1,0);for(int i=2;i<=S;i++) tr[i].init();m=rd();for(int i=1;i<=m;i++) {int u=id[rd()], v=id[rd()], l=ori_tree::lca(u,v), step=rd();pii s1=group(u,l,step), s2=group(v,l,step);int ans=s1.first+s2.first, res=s1.second+s2.second;if(res) ans+=1+(res>step);printf("%d\n",ans);}
}

Codechef :Children Trips/TRIPS(树分块)相关推荐

  1. BZOJ 1086 [SCOI2005]王室联邦(树分块)

    题意:中文题,略 思路:秦皇岛前就一直想学,后来没怎么想通,就算了.现在雅不是很懂,一直似懂非懂的,对于树分块的种类,有位聚聚已经整理好了(传送门),其他的就是直接搜索分块 代码: #include ...

  2. 【BZOJ】3052: [wc2013]糖果公园 树分块+带修改莫队算法

    [题目]#58. [WC2013]糖果公园 [题意]给定n个点的树,m种糖果,每个点有糖果ci.给定n个数wi和m个数vi,第i颗糖果第j次品尝的价值是v(i)*w(j).q次询问一条链上每个点价值的 ...

  3. 19.CF803G Periodic RMQ Problem 线段树+分块+线段树标记

    19.CF803G Periodic RMQ Problem 线段树+分块+线段树标记 个人Limitの线段树题单题解主目录:Limitの线段树题单 题解目录_HeartFireY的博客-CSDN博客 ...

  4. Codechef SEAARC Sereja and Arcs (分块、组合计数)

    我现在真的什么都不会了呢...... 题目链接: https://www.codechef.com/problems/SEAARC 好吧,这题其实考察的是枚举的功力-- 题目要求的是\(ABAB\)的 ...

  5. Codechef SEAARC Sereja and Arcs (分块)

    我现在真的什么都不会了呢...... 题目链接: https://www.codechef.com/problems/SEAARC 好吧,这题其实考察的是枚举的功力-- 题目要求的是\(ABAB\)的 ...

  6. [Bzoj4260]Codechef REBXOR(trie树)

    4260: Codechef REBXOR Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 1534  Solved: 669 [Submit][St ...

  7. CF966E-May Holidays【虚树,分块】

    正题 题目链接:https://codeforces.ml/contest/966/problem/E 题目大意 nnn个点的一棵树,每个点有一个tit_iti​,每次修改一个点是否为关键点,每次修改 ...

  8. jquery 遍历无限极树_jQuery parent()和children()树遍历函数示例

    jquery 遍历无限极树 jQuery provides a lot of tree traversal functions that we can use to get the parent, c ...

  9. 「一题多解」【CodeForces 85D】Sum of Medians(线段树 / 分块)

    题目链接 [CodeForces 85D]Sum of Medians 题目大意 实现一个setsetset,支持插入,删除,求∑a5k+3∑a5k+3\sum a_{5k+3}.注意,setsets ...

最新文章

  1. 数据结构之队列、双端队列
  2. [BZOJ4557][JLOI2016]侦查守卫
  3. ttk python_【转】Python GUI进阶(ttk)—让界面变得更美
  4. oracle 服务管理,管理 Oracle 内容服务类别
  5. 5年前面试题引发的“血案”(番外篇)(总结和乱侃)
  6. H.264专利费不受FRAND限制 Android设备商受影响
  7. 宝塔php安装那个合_使用宝塔面板安装nextcloud | 启用本地存储 | 安装smbclient
  8. 1.7 编程基础之字符串 31 字符串p型编码 python
  9. 实例:用户登录(python 版)
  10. Fiddler--QUICKEXER
  11. 4.5 为什么使用深层表示
  12. 利用opencv 做一个疲劳检测系统(2)
  13. 【java web学习小结】JSP的response对象的动态响应实例
  14. HDU-3237 Help Bubu(状压dp)
  15. HTTP状态码滑稽表情包
  16. 领导力提升的科学:如何提升领导力?
  17. android开发中磁场传感器,Android NDK中的陀螺仪和磁场传感器事件
  18. G、S、C、P、T STATE
  19. 刘意-java基础视频(API-IO流)笔记(一)
  20. 推荐算法(3):利用用户标签数据

热门文章

  1. 别开玩笑了!特种兵式旅游,胆小勿进!
  2. 给自己起个好听的英文名字
  3. c语言微信自动跳一跳,C/C++知识点之微信跳一跳辅助c++实现 轻松上万
  4. IT安全交给MSP,企业能当“甩手掌柜”吗?
  5. JAVA 中文字符转为拼音字符串
  6. JS的定时器和清除定时器
  7. 力扣 754. 到达终点数字
  8. 【论文翻译】An Attention Enhanced Graph Convolutional LSTM Network for Skeleton-Based Action Recognition
  9. 李笑来的新书《定投》
  10. 魔法少女 计蒜客 - T1551(动态规划)