浅谈离线分治算法:https://www.cnblogs.com/AKMer/p/10415556.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=4009

树套树写法:https://www.cnblogs.com/AKMer/p/10181501.html

把二维线段树部分改成整体二分就行了。

时间复杂度:\(O(nlog^2n)\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
#define low(i) ((i)&(-(i))) const int maxn=4e4+5; bool bo[maxn*5];
int n,P,Q,tot,cnt,sum;int f[maxn][17];
int now[maxn],pre[maxn<<1],son[maxn<<1];
int dep[maxn],siz[maxn],dfn[maxn],ans[maxn]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} void add(int a,int b) {
pre[++tot]=now[a];
now[a]=tot,son[tot]=b;
} void dfs(int fa,int u) {
siz[u]=1,dfn[u]=++cnt;
f[u][0]=fa,dep[u]=dep[fa]+1;
for(int i=1;i<17;i++)
f[u][i]=f[f[u][i-1]][i-1];
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(v!=fa)dfs(u,v),siz[u]+=siz[v];
} struct Oper {
int opt,x,y1,y2,k; Oper() {} Oper(int _opt,int _x,int _y1,int _y2,int _k) {
opt=_opt,x=_x,y1=_y1,y2=_y2,k=_k;
} bool operator<(const Oper &a)const {
if(x==a.x)return (opt!=0)>(a.opt!=0);
return x<a.x;
}
}p[maxn*5],tmp[maxn*5]; struct tree_array {
int c[maxn]; void add(int pos,int v) {
for(int i=pos;i<=n;i+=low(i))
c[i]+=v;
} int query(int pos) {
int res=0;
for(int i=pos;i;i-=low(i))
res+=c[i];
return res;
}
}T; void solve(int l,int r,int st,int ed) {
if(ed<st)return;
if(l==r) {
for(int i=st;i<=ed;i++)
if(!p[i].opt)ans[p[i].y2]=l;
return;
}
int mid=(l+r)>>1,num=0;
for(int i=st;i<=ed;i++)
if(p[i].opt) {
if(p[i].k<=mid) {
bo[i]=1,num++;
T.add(p[i].y1,p[i].opt);
T.add(p[i].y2+1,-p[i].opt);
}
else bo[i]=0;
}
else {
int res=T.query(p[i].y1);
if(res>=p[i].k)bo[i]=1,num++;
else bo[i]=0,p[i].k-=res;
}
for(int i=st;i<=ed;i++)
if(p[i].opt&&p[i].k<=mid) {
T.add(p[i].y1,-p[i].opt);
T.add(p[i].y2+1,p[i].opt);
}
int ED=st,ST=st+num;
for(int i=st;i<=ed;i++)
if(bo[i])tmp[ED++]=p[i];
else tmp[ST++]=p[i];
for(int i=st;i<=ed;i++)
p[i]=tmp[i];
solve(l,mid,st,ED-1),solve(mid+1,r,ED,ed);
} int main() {
n=read(),P=read(),Q=read();
for(int i=1;i<n;i++) {
int x=read(),y=read();
add(x,y),add(y,x);
}
dfs(0,1);
for(int i=1;i<=P;i++) {
int u=read(),v=read(),c=read();
if(dfn[u]>dfn[v])swap(u,v);
if(dfn[u]+siz[u]-1>=dfn[v]+siz[v]-1) {
int pos=v;
for(int i=16;~i;i--)
if(dep[f[pos][i]]>dep[u])
pos=f[pos][i];
p[++sum]=Oper(1,1,dfn[v],dfn[v]+siz[v]-1,c);
p[++sum]=Oper(-1,dfn[pos],dfn[v],dfn[v]+siz[v]-1,c);
p[++sum]=Oper(1,dfn[v],dfn[pos]+siz[pos],n,c);
p[++sum]=Oper(-1,dfn[v]+siz[v],dfn[pos]+siz[pos],n,c);
}
else {
p[++sum]=Oper(1,dfn[u],dfn[v],dfn[v]+siz[v]-1,c);
p[++sum]=Oper(-1,dfn[u]+siz[u],dfn[v],dfn[v]+siz[v]-1,c);
}
}
for(int i=1;i<=Q;i++) {
int u=read(),v=read(),k=read();
if(dfn[u]>dfn[v])swap(u,v);
p[++sum]=Oper(0,dfn[u],dfn[v],i,k);
}
sort(p+1,p+sum+1);
solve(1,1e9,1,sum);
for(int i=1;i<=Q;i++)
printf("%d\n",ans[i]);
return 0;
}

BZOJ4009:[HNOI2015]接水果(整体二分版)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. [HNOI2015]接水果[整体二分]

    [HNOI2015]接水果 给出一个树上路径集合\(S\) 多次询问\(x,y\)中的\(k\)小值 如果你问我数列上那么我会 树上的话 树上差分了吧直接?- 令 \(st_x<st_y\) 1 ...

  7. 2018.10.02 bzoj4009: [HNOI2015]接水果(整体二分)

    传送门 整体二分好题. 考虑水果被盘子接住的条件. 不妨设水果表示的路径为(x1,y1)(x_1,y_1)(x1​,y1​),盘子表示的为(x2,y2)(x_2,y_2)(x2​,y2​) 不妨设df ...

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

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

  9. bzoj4009: [HNOI2015]接水果(整体二分)

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

随机推荐

  1. JQuery3 的新变化

    1. for-of 循环 for-in 循环不被推荐遍历数组,forEach 循环不能中断,for-of 循环(ES6)则弥补了前两者的不足,又添加了更多拓展(比如能遍历字符串,DOM 元素等) 因此 ...

  2. [POI2007]立方体大作战tet

    题目 BZOJ 洛谷 做法 很巧妙的题,注意每种颜色只有两个 消除一种颜色,其实就是看中间有多少个没有被消除的块,这种动态距离问题显然能用树状数组解决 洛谷输出方案,暴力往下爬就行 My comple ...

  3. Linux与Android 多点触摸协议【转】

    本文转载自:http://blog.csdn.net/xubin341719/article/details/7833277 一.Linux与Android 多点触摸协议 为了使用功能强大的多点触控设 ...

  4. mongodb的原子性(Atomicity)和事物 (Transactions)

    在mongodb中,单个的写操作保持原子性是在单个的document 上. $isolated operator $isolated 一个写操作多个documents 的时候可以防止和其他进程交织,一 ...

  5. PowerDesigner生成数据库表和逆向生成表结构(MySQL数据库)

    一.Download Connector/ODBC下载ODBC驱动,地址:https://dev.mysql.com/downloads/connector/odbc/, 需要注意:PowerDesi ...

  6. Android Sqlite 批量插入性能优化

    db.beginTransaction(); try { for (...) { db.execSQL("...", new Object[]{}); } db.setTransa ...

  7. ASP.NET上传文件,已经上传的大小保存在session中,在另一个页面中读取session的值不行

    想自己做个ASP.NET上传文件时显示进度条的, 按照自己的想法,其实也就是显示每次已经上传的字节,从网上找到一个方法是能够把文件变成流以后再慢慢写入的,我在那个循环写入的时候每循环一次都把已经上传的 ...

  8. 这样子覆盖jquery的$

    window.$ = function(){ alert('nihao'); } window.ad = function(){ alert('nihao1'); } !function($){ $( ...

  9. java: Comparable比较器,数组对象比较器

    Arrays只适合一个数组/对象内的数值进行比较, Comparable比较器(Compara)适合数组,对象,队列等排序, Comparable是一个接口类,实现此接口必须复写:compareTo ...

  10. sikiA计划问题记录

    1.有时候在场景中创建光源会有一条虚线 解决方法:禁用锯齿 edit - project setting - quality - anti aliasing