[HNOI2015]接水果

给出一个树上路径集合\(S\) 多次询问\(x,y\)中的\(k\)小值

如果你问我数列上那么我会

树上的话 树上差分了吧直接?…

令 \(st_x<st_y\)

1.假设 \(LCA(x,y) == x\)

(学过树的人都知道不可能等于y)

然后树剖乱跳到一个路径上不在 \(x->y\) 上的 \(z\) 就可以了

\([1,st_z-1] or [st_z+1,n]\)

2.1假设不成立…

那么一个点在 \([st_x,ed_x]\) , 另一个在 \([st_y,ed_y]\) 里面就可以了…

#include <bits/stdc++.h>
#define rep(a , b , c) for(register int a = b ; a <= c ; ++ a)
#define Rep(a , b , c) for(register int a = b ; a >= c ; -- a)
#define go(u) for(register int i = G.head[u] , v = G.to[i] , w = G.dis[i] ; i ; v = G.to[i = G.nxt[i]] , w = G.dis[i])
using namespace std ;
inline int read() {
int x = 0 ; bool f = 1 ; char c = getchar() ;
while(c < 48 || c > 57) { if(c == '-') f = 0 ; c = getchar() ; }
while(c > 47 && c < 58) { x = (x << 1) + (x << 3) + (c & 15) ; c = getchar() ; }
return f ? x : -x ;
}
template <class T> inline void print(T x , char c = '\n') {
static char st[100] ; int stp = 0 ;
if(! x) { putchar('0') ; }
if(x < 0) { x = -x ; putchar('-') ; }
while(x) { st[++ stp] = x % 10 ^ 48 ; x /= 10 ; }
while(stp) { putchar(st[stp --]) ; } putchar(c) ;
}
template <class T> void cmax(T & x , T y) { x < y ? x = y : 0 ; }
template <class T> void cmin(T & x , T y) { x > y ? x = y : 0 ; }
const int _N = 1e6 + 10 ;
struct Group {
int head[_N] , nxt[_N << 1] , to[_N] , dis[_N] , cnt = 1 ;
void init() { memset(head , 0 , sizeof(head)) ; cnt = 1 ; }
inline void add(int u , int v , int w = 1) { nxt[++ cnt] = head[u] ; to[cnt] = v ; dis[cnt] = w ; head[u] = cnt ; }
} ;
const int N = 4e4 + 10 ;
typedef int arr[N] ;
int n , m , Q , len , cnt ;
arr ans , b , sz , fa , d , son , top , st , ed ;
struct Qry {
int opt , x , l , r , k , v , id ;
bool operator < (const Qry & other) const { if(x != other.x) return x < other.x ; return opt < other.opt ; }
} q[N << 3] , q1[N << 3] , q2[N << 3] ;
Group G ;
void dfs(int u) { sz[u] = 1 ; go(u) if(v != fa[u]) { d[v] = d[u] + 1 ; fa[v] = u ; dfs(v) ; sz[u] += sz[v] ; if(sz[v] > sz[son[u]]) son[u] = v ;} }
int idx = 0 ;
void dfs(int u , int t) { st[u] = ++ idx ; top[u] = t ; if(son[u]) dfs(son[u] , t) ; go(u) if(v != fa[u] && v != son[u]) dfs(v , v) ; ed[u] = idx ; }
inline int Lca(int x , int y) { while(top[x] != top[y]) { if(d[top[x]] < d[top[y]]) swap(x , y) ; x = fa[top[x]] ; } return d[x] < d[y] ? x : y ; }
inline int getson(int x , int y) { while(top[x] != top[y]) { if(fa[top[x]] == y) return top[x] ; x = fa[top[x]] ; } return son[y] ; }
struct BIT {
int c[N] ; inline int low(int x) { return x & -x ; }
inline void add(int x , int y) { for( ; x <= n ; x += low(x)) c[x] += y ; }
inline int query(int x) { int ans = 0 ; for( ; x ; x ^= low(x)) ans += c[x] ; return ans ; }
} t ;
void solve(int L , int R , int l , int r) {
if(L > R) return ;
if(l == r) { rep(i , L , R) if(q[i].opt == 2) { ans[q[i].id] = l ; } return ; }
int mid = l + r >> 1 , cnt1 = 0 , cnt2 = 0 ;
rep(i , L , R) {
if(q[i].opt == 1) {
if(q[i].k <= mid) { t.add(q[i].l , q[i].v) ; t.add(q[i].r + 1 , -q[i].v) ; q1[++ cnt1] = q[i] ; }
else q2[++ cnt2] = q[i] ;
}
else { int val = t.query(q[i].l) ; if(q[i].k <= val) { q1[++ cnt1] = q[i] ; } else { q[i].k -= val ; q2[++ cnt2] = q[i] ; } }
}
rep(i , 1 , cnt1) q[L + i - 1] = q1[i] ; rep(i , 1 , cnt2) q[L + i + cnt1 - 1] = q2[i] ;
solve(L , L + cnt1 - 1 , l , mid) ; solve(L + cnt1 , R , mid + 1 , r) ;
}
signed main() {
n = read() ; m = read() ; Q = read() ;
rep(i , 2 , n) { int x = read() , y = read() ; G.add(x , y) ; G.add(y , x) ; } dfs(1) ; dfs(1 , 1) ;
rep(i , 1 , m) {
int x = read() , y = read() , k = read() ; b[++ len] = k ;
if(st[x] > st[y]) swap(x , y) ;
int lca = Lca(x , y) ;
if(lca == x) {
int z = getson(y , x) ;
if(st[z] > 1) { q[++ cnt] = { 1 , 1 , st[y] , ed[y] , k , 1 , 0 } ; q[++ cnt] = { 1 , st[z] , st[y] , ed[y] , k , -1 , 0 } ; }
if(ed[z] < n) { q[++ cnt] = { 1 , st[y] , ed[z] + 1 , n , k , 1 , 0 } ; q[++ cnt] = { 1 , ed[y] + 1 , ed[z] + 1 , n , k , -1 , 0 } ; }
}
else { q[++ cnt] = { 1 , st[x] , st[y] , ed[y] , k , 1 , 0 } ; q[++ cnt] = { 1 , ed[x] + 1 , st[y] , ed[y] , k , -1 , 0 } ; }
} sort(b + 1 , b + len + 1) ; len = unique(b + 1 , b + len + 1) - b - 1 ;
rep(i , 1 , cnt) q[i].k = lower_bound(b + 1 , b + len + 1 , q[i].k) - b ;
rep(i , 1 , Q) {
int x = read() , y = read() , k = read() ;
if(st[x] > st[y]) swap(x , y) ;
q[++ cnt] = { 2 , st[x] , st[y] , 0 , k , 0 , i } ;
} sort(q + 1 , q + cnt + 1) ; solve(1 , cnt , 1 , len) ;
for(int i = 1 ; i <= Q ; i ++) print(b[ans[i]]) ;
return 0 ;
}

[HNOI2015]接水果[整体二分]的更多相关文章

  1. [BZOJ4009][HNOI2015]接水果(整体二分)

    [HNOI2015]接水果 时间限制:60s      空间限制:512MB 题目描述 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The b ...

  2. BZOJ.4009.[HNOI2015]接水果(整体二分 扫描线)

    LOJ BZOJ 洛谷 又是一个三OJ rank1!=w= \(Description\) (还是感觉,为啥非要出那种题目背景啊=-=直接说不好么) 给定一棵树和一个路径集合(每条路径有一个权值).\ ...

  3. [bzoj4009] [HNOI2015]接水果 整体二分+扫描线+dfs序+树状数组

    Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更 加 ...

  4. BZOJ4009:[HNOI2015]接水果(整体二分版)

    浅谈离线分治算法:https://www.cnblogs.com/AKMer/p/10415556.html 题目传送门:https://lydsy.com/JudgeOnline/problem.p ...

  5. BZOJ 4009: [HNOI2015]接水果 (整体二分+扫描线 树状数组)

    整体二分+扫描线 树状数组 具体做法看这里a CODE #include <cctype> #include <cstdio> #include <cstring> ...

  6. bzoj4009 [HNOI2015]接水果 整体二分+扫描线+树状数组+dfs序

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4009 题解 考虑怎样的情况就会有一个链覆盖另一个链. 设被覆盖的链为 \(a - b\),覆盖 ...

  7. [HNOI2015][bzoj4009] 接水果 [整体二分+扫描线]

    题面 传送门 思路 本题其实有在线做法......但是太难写了,退而求其次写了离线 基本思路就是,考虑一个盘子以及它能接到的所有水果 可以发现,这个水果的端点一定在这个盘子两端的"子树&qu ...

  8. luogu3242 接水果 (整体二分+树状数组)

    考虑整体二分,问题就变成了每个(水果)路径有多少个满足条件(权值)的(盘子)子路径 考虑一个盘子(a,b)表示两端点(不妨设dfn[a]<dfn[b]),那么他能接到的水果(u,v)一定满足(不 ...

  9. bzoj 4009 接水果 整体二分

    Description 先给出一些盘子, 用路径x-y表示, 有权值 再有Q个询问, 表示水果, 用路径x-y表示 如果盘子是水果的子路径, 可以接住 对于每个水果, 输出可以接住它的盘子的第k小权 ...

随机推荐

  1. TTStand 基础知识[8] Build-In StepTypes(3)

    Build-In Step Types的最后一篇,前面两篇的连接如下: TestStand 基础知识[7] Build-In StepTypes(2) TestStand 基础知识[6] Build- ...

  2. 业余无线电A类考试准备笔记

    在线模拟自测地址:https://liunan.github.io/crac/ 共361题,到LK0074 1004/2890行 Key Word: 要合法 要服从管理 Note: 无线电管理 最高法 ...

  3. Dockerfile的使用

    一 什么是Dockerfile Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像. 1.对于开发人员:可以为开发团队提供一个完全一致的开发环境: 2.对 ...

  4. Java压缩包(zip)【学习笔记】

    前言 Java实现Zip压缩解压可以使用JDK的原生类java.util.zip,但是JDK 7 之前存在中文文件名乱码问题. 使用 ant.jar 的org.apache.tools.zip包,可以 ...

  5. Springboot 自动装配置

    Spring Boot 相对于传统的Spring引入了自动配置功能,简化了项目中繁琐的配置,让开发者利用起来更加的简便.快捷.比如内嵌的tomcat容器等,这些都属于Spring Boot自动配置的范 ...

  6. 忘记centos的root用户密码怎么办?

    1 重置centos7管理员密码 1.1 重置centos7管理员密码的几个步骤 1)重启服务器后,在grub菜单界面,根据界面显示的提示信息,按 e 进入编辑模式.注意:是否开启selinux,重置 ...

  7. 使用Webpack的代码拆分在Vue中进行懒加载

    参考学习:https://alexjover.com/blog/lazy-load-in-vue-using-webpack-s-code-splitting/ 学习文案:https://webpac ...

  8. 复杂系统架构设计<1>

    这两天开始读由Edward Crawley(爱德华 克劳利).Bruce Cameron(布鲁斯 卡梅隆).Daniel Selva(丹尼尔 塞尔瓦)著作的系统架构,一开始看目录以为是介绍系统软件架构 ...

  9. [MySQL] mysql索引的长度计算和联合索引

    1.所有的索引字段,如果没有设置not null,则需要加一个字节.2.定长字段,int占4个字节.date占3个字节.char(n)占n个字符.3.变长字段,varchar(n),则有n个字符+两个 ...

  10. Linux 使用vim命令编辑文件内容

    在终端可以使用vim命令来直接编辑文件内容. vim,也可以叫做vi. vim有三种模式:命令模式.输入模式.底线命令模式. 命令模式 vim  文件名   进入命令模式,vim也可以写成vi. 如果 ...