学了差不多一星期的主席树+树链剖分,再来看这题发现其实是个板子题

一开始想复杂了,以为要用类似求树上第k大的树上差分思想来解决这道题,但其实树链上<=k的元素个数其实直接可以用树链剖分来求

具体是把每条树链放到主席树上询问一下求和就好了

#include<bits/stdc++.h>
using namespace std;
#define maxn 100006
struct Edge{int to,nxt,w;}edge[maxn<<];
int b[maxn],n,m,a[maxn],head[maxn],tot;
void init(){memset(head,-,sizeof head);tot=;}
void addedge(int u,int v,int w){
edge[tot].to=v;edge[tot].nxt=head[u];edge[tot].w=w;head[u]=tot++;
}
struct Node{int lc,rc,sum;}T[maxn*];
int siz,rt[maxn];
int build(int l,int r){
int now=++siz;
T[now].lc=T[now].rc=T[now].sum=;
if(l==r)return now;
int mid=l+r>>;
T[now].lc=build(l,mid);
T[now].rc=build(mid+,r);
return now;
}
int update(int last,int pos,int l,int r){//更新到pos点
int now=++siz;
T[now]=T[last];T[now].sum++;
if(l==r)return now;
int mid=l+r>>;
if(pos<=mid)T[now].lc=update(T[last].lc,pos,l,mid);
else T[now].rc=update(T[last].rc,pos,mid+,r);
return now;
}
int query(int st,int ed,int L,int R,int l,int r){
if(L<=l && R>=r)return T[ed].sum-T[st].sum;
int mid=l+r>>,res=;
if(L<=mid)res+=query(T[st].lc,T[ed].lc,L,R,l,mid);
if(R>mid)res+=query(T[st].rc,T[ed].rc,L,R,mid+,r);
return res;
} int f[maxn],son[maxn],d[maxn],size[maxn];
void dfs1(int x,int pre,int deep){
f[x]=pre;size[x]=;d[x]=deep;
for(int i=head[x];i!=-;i=edge[i].nxt){
int y=edge[i].to;
if(y==pre)continue;
a[y]=edge[i].w;
dfs1(y,x,deep+);
size[x]+=size[y];
if(size[y]>size[son[x]])son[x]=y;
}
}
int id[maxn],rk[maxn],idx,top[maxn];
void dfs2(int x,int tp){
top[x]=tp;id[x]=++idx;rk[idx]=x;
if(son[x])dfs2(son[x],tp);
for(int i=head[x];i!=-;i=edge[i].nxt){
int y=edge[i].to;
if(y!=son[x] && y!=f[x])dfs2(y,y);
}
} int Query(int x,int y,int pos){
int res=;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]])swap(x,y);
res+=query(rt[id[top[x]]-],rt[id[x]],,pos,,m);
x=f[top[x]];
}
if(id[x]>id[y])swap(x,y);
res+=query(rt[id[x]],rt[id[y]],,pos,,m);
return res;
}
int main(){int q;init();
cin>>n>>q;int u,v,w,k;
for(int i=;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);addedge(v,u,w);
} a[]=0x3f3f3f3f;
siz=;dfs1(,,);dfs2(,);//树剖
for(int i=;i<=n;i++)b[++m]=a[i];
sort(b+,b++m);
m=unique(b+,b++m)-(b+);
rt[]=build(,m);
for(int i=;i<=idx;i++){
int pos=lower_bound(b+,b++m,a[rk[i]])-b;
rt[i]=update(rt[i-],pos,,m);
} while(q--){
scanf("%d%d%d",&u,&v,&k);
int pos=upper_bound(b+,b++m,k)-(b+);
if(pos==){puts("");continue;}
else cout<<Query(u,v,pos)<<'\n';
}
}

主席树+树链剖分——南昌邀请赛Distance on the tree的更多相关文章

  1. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

  2. BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)

    题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...

  3. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

  4. UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...

  5. BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP

    题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...

  6. CF487E Tourists 圆方树、树链剖分

    传送门 注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点 注意:这里不能缩边双联通分量,样例\(2\)就 ...

  7. 2019.01.08 codeforces 1009F. Dominant Indices(长链剖分)

    传送门 长链剖分模板题. 题意:给出一棵树,设fi,jf_{i,j}fi,j​表示iii的子树中距离点iii距离为jjj的点的个数,现在对于每个点iii要求出使得fif_ifi​取得最大值的那个jjj ...

  8. 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)

    LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...

  9. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

随机推荐

  1. 【THUSC2017】【LOJ2978】杜老师 高斯消元

    题目大意 给你 \(l,r\),求从 \(l\) 到 \(r\) 这 \(r-l+1\) 个数中能选出多少个不同的子集,满足子集中所有的数的乘积是一个完全平方数. 对 \(998244353\) 取模 ...

  2. IDictionary使用/声明

    因为不常用,老师忘记怎么申明..这次记下来,哪天用了又忘了就来翻翻 主要代码 IDictionary<string, string> openWith = new Dictionary&l ...

  3. python并发编程之多进程基础知识点

    1.操作系统 位于硬件与应用软件之间,本质也是一种软件,由系统内核和系统接口组成 和进程之间的关系是: 进程只能由操作系统创建 和普通软件区别: 操作系统是真正的控制硬件 应用程序实际在调用操作系统提 ...

  4. gcc编译C源文件

    gcc编译C程序的主要过程是:预处理---编译---汇编---连接,其中:(以名为hello.c的源文件为例) 预处理:对各种预处理指令(#开头,如#include,#define)进行处理,以及删除 ...

  5. JS学习笔记Day18

    一.轮播图 二.重力弹球 三.计时器

  6. percona-xtrabackup快速安装及其简单使用

    percona-xtrabackup快速安装及其简单使用 cd /opt/环境:centos6.x yum -y install perl-DBIyum -y install perl-DBD-MyS ...

  7. keras使用

    一.pad_sequences from keras.preprocessing.sequence import pad_sequences keras只能接受长度相同的序列输入.因此如果目前序列长度 ...

  8. 编写高质量的Python代码系列(五)之并发与并行

    用Python可以很容易就能写出并发程序,这种程序可以在同一时间做许多间不同的事情.我们也可以通过系统调用.子进程(subprocess)及C语言扩展来实现并行处理. 第三十六条: 用subproce ...

  9. [Leetcode] 01 Matrix

    问题: https://leetcode.com/problems/01-matrix/#/description 基本思路:广度优先遍历,根据所有最短距离为N的格找到所有距离为N+1的格,直到所有的 ...

  10. python的多线程

    1.多线程的例子 import threading #首先导入threading模块,这是使用多线程的前提 from time import ctime,sleep def music(func): ...