Description

风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果。

由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更

加难的版本。首先有一个地图,是一棵由 n 个顶点、n-1 条边组成的树(例如图 1

给出的树包含 8 个顶点、7 条边)。这颗树上有 P 个盘子,每个盘子实际上是一条

路径(例如图 1 中顶点 6 到顶点 8 的路径),并且每个盘子还有一个权值。第 i 个

盘子就是顶点a_i到顶点b_i的路径(由于是树,所以从a_i到b_i的路径是唯一的),

权值为c_i。接下来依次会有Q个水果掉下来,每个水果本质上也是一条路径,第

i 个水果是从顶点 u_i 到顶点v_i 的路径。幽香每次需要选择一个盘子去接当前的水

果:一个盘子能接住一个水果,当且仅当盘子的路径是水果的路径的子路径(例如

图1中从 3到7 的路径是从1到8的路径的子路径)。这里规定:从a 到b的路径与

从b到 a的路径是同一条路径。当然为了提高难度,对于第 i 个水果,你需要选择

能接住它的所有盘子中,权值第 k_i 小的那个盘子,每个盘子可重复使用(没有使用次数

的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水

果路径的子路径)。幽香认为这个游戏很难,你能轻松解决给她看吗?

Input

第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数。

接下来n-1 行,每行两个数 a、b,表示树上的a和b 之间有一条边。树中顶点

按1到 n标号。 接下来 P 行,每行三个数 a、b、c,表示路径为 a 到 b、权值为 c 的盘子,其

中0≤c≤10^9,a不等于b。

接下来Q行,每行三个数 u、v、k,表示路径为 u到 v的水果,其中 u不等于v,你需要选择第 k小的盘子,

第k 小一定存在。

Output

对于每个果子,输出一行表示选择的盘子的权值。

Sample Input

10 10 10

1 2

2 3

3 4

4 5

5 6

6 7

7 8

8 9

9 10

3 2 217394434

10 7 13022269

6 7 283254485

6 8 333042360

4 6 442139372

8 3 225045590

10 4 922205209

10 8 808296330

9 2 486331361

4 9 551176338

1 8 5

3 8 3

3 8 4

1 8 3

4 8 1

2 3 1

2 3 1

2 3 1

2 4 1

1 4 1

Sample Output

442139372

333042360

442139372

283254485

283254485

217394434

217394434

217394434

217394434

217394434

HINT

N,P,Q<=40000。

Source

Solution

本题简化题意:n个结点的树,给定m条带权值的路径(端点不重合),q个询问,每个询问给定一条路径,查询m条路径中所有它的子路径的权值第k小。

首先如果两个路径有包含关系,那么是可以用dfs序的区间表示的,具体看代码,所以我们可以把集合中的两个dfs序区间看成二维平面上的一个矩形,然后询问看成一个点,这样题意就转化成了包含一个点的矩形中权值第k大的,然后我们二分答案,就成了判定性问题,判断够不够k个,这样就可以直接用扫描线做啦。然后二分的话复杂度爆炸,所以要整体二分,在整体二分时候的细节见代码,用树状数组+排序就可以解决二维数点问题。

Code

#include <bits/stdc++.h>
#define N 40005
using namespace std;
struct nod
{
int x,y,z,v,w;
nod(int a=0,int b=0,int c=0,int d=0,int e=0){x=a,y=b,z=c,v=d,w=e;}
bool operator<(const nod &a)const{return x<a.x;}
}a[N*3],q[N*2],t[N*2];
int n,m,k,x,y,z,g,he[N],to[N<<1],ne[N<<1],cnt,anc[N][20],dep[N],in[N],ou[N],I,tot,f[N],val[N],vl[N],ans[N];
bool cmp(nod a,nod b){return a.v<b.v;}
void add(int x,int y){to[++cnt]=y,ne[cnt]=he[x],he[x]=cnt;}
void dfs(int x)
{
in[x]=++I;for(int i=1;i<=15;i++) anc[x][i]=anc[anc[x][i-1]][i-1];
for(int i=he[x],y;i;i=ne[i]) if((y=to[i])!=anc[x][0]) anc[y][0]=x,dep[y]=dep[x]+1,dfs(y);
ou[x]=I;
}
int find(int x,int y){for(int i=15;~i;i--) if((1<<i)<=y) x=anc[x][i],y-=(1<<i);return x;}
void upd(int x,int a){for(int i=x;i<=n;i+=i&-i) f[i]+=a;}
int que(int x){int ans=0;for(int i=x;i;i-=i&-i) ans+=f[i];return ans;}
void solve(int b,int e,int l,int r,int L,int R)//be:询问 lr:修改 LR:权值
{
if(b>e) return;
if(L==R){for(int i=b;i<=e;i++) ans[q[i].z]=L;return;}//权值只有一种,直接记录区间内的答案
int MID=(L+R)>>1,mid=l-1,p=l;//整体二分时,只用扫左一半的修改,然后如果数量不够就在以后的右边进行递归处理,够就在以后的左边进行递归处理
for(int i=b;i<=e;i++) vl[q[i].z]=0;sort(a+l,a+r+1,cmp);
while(mid<r&&a[mid+1].v<=MID) mid++;sort(a+l,a+mid+1);
for(int i=b;i<=e;i++)
{
while(p<=mid&&a[p].x<=q[i].x) upd(a[p].y,a[p].w),upd(a[p].z+1,-a[p].w),p++;
vl[q[i].z]+=que(q[i].y);//对每个点累加覆盖它的矩阵
}
while(p>l) p--,upd(a[p].y,-a[p].w),upd(a[p].z+1,a[p].w);//还原
for(int i=(p=b);i<=e;i++) if(val[q[i].z]<=vl[q[i].z]) t[p++]=q[i];//够的
for(int i=(p=e);i>=b;i--) if(val[q[i].z]>vl[q[i].z]) t[p--]=q[i];//不够的
for(int i=b;i<=e;q[i]=t[i],i++) if(~vl[q[i].z]&&val[q[i].z]>vl[q[i].z]) val[q[i].z]-=vl[q[i].z],vl[q[i].z]=-1;//减去已经覆盖的
solve(b,p,l,mid,L,MID),solve(p+1,e,mid+1,r,MID+1,R);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=2;i<=n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs(1);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
if(dep[x]>dep[y]) swap(x,y);
if(dep[x]<dep[y]&&anc[g=find(y,dep[y]-dep[x]-1)][0]==x)//x是y的祖先,xy路径上x的直系儿子子树之外->y子树之内的路径都可以
{
a[++tot]=nod(1,in[y],ou[y],z,1);
a[++tot]=nod(in[g],in[y],ou[y],z,-1);
a[++tot]=nod(ou[g]+1,in[y],ou[y],z,1);//右端点是n,所以不用添加
}
else a[++tot]=nod(in[x],in[y],ou[y],z,1),a[++tot]=nod(ou[x]+1,in[y],ou[y],z,-1);//x和y没有祖先关系,x的子树内->y的子树内的路径都可以
}
for(int i=1;i<=k;i++) scanf("%d%d%d",&x,&y,&val[i]),q[i]=nod(in[x],in[y],i,0,0),q[i+k]=nod(in[y],in[x],i,0,0);
sort(q+1,q+k*2+1),solve(1,k*2,1,tot,1,1000000000);
for(int i=1;i<=k;i++)printf("%d\n",ans[i]);
}

[bzoj4009] [HNOI2015]接水果 整体二分+扫描线+dfs序+树状数组的更多相关文章

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

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

  2. 计蒜客A1998 Ka Chang (分块+dfs序+树状数组)

    题意 给你一个\(1e5\)的有点权的树,有\(1e5\)个操作: 1.给第\(x\)层的点加上\(y\) 2.求以\(x\)为根的子树的点权和 思路 首先处理出层数为x的所有点 操作2一般都是用df ...

  3. HDU 3887:Counting Offspring(DFS序+树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=3887 题意:给出一个有根树,问对于每一个节点它的子树中有多少个节点的值是小于它的. 思路:这题和那道苹果树是一样 ...

  4. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  5. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  6. BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )

    一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...

  7. 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组

    题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  8. [BZOJ1103][POI2007]大都市meg dfs序+树状数组

    Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n ...

  9. 2018.10.20 NOIP模拟 巧克力(trie树+dfs序+树状数组)

    传送门 好题啊. 考虑前面的32分,直接维护后缀trietrietrie树就行了. 如果#号不在字符串首? 只需要维护第一个#前面的字符串和最后一个#后面的字符串. 分开用两棵trie树并且维护第一棵 ...

随机推荐

  1. VMware 克隆网卡无法启动

    问题描述: 最近学习 hadoop,环境准备搭建在虚拟机之上,装好一台虚拟机克隆完成后,网卡无法启动. 多年前,初学 Linux 的时候,就遇到过这个问题,记录的笔记找不到了,简单记录一下. shel ...

  2. JDK8新特性:函数式接口@FunctionalInterface的使用说明

    我们常用的一些接口Callable.Runnable.Comparator等在JDK8中都添加了@FunctionalInterface注解. 通过JDK8源码javadoc,可以知道这个注解有以下特 ...

  3. Android开发之获取系统所有进程信息。

    最近在做一个app,有一个进程管理模块用于管理系统中正在运行的进程,并且可以关闭进程进行加速手机的功能,基本把它实现了出来.界面的效果都是自己写的,虽然有BUG,但是基本上能满足需求,后期我会改进BU ...

  4. win10系统的快捷键

    1.win10特有的快捷键:任务视图和虚拟桌面相关 (1)Win + Tab:查看任务视图 (2)Win + Ctrl + D:在任务视图中新建虚拟桌面 (3)Win + Ctrl + F4:关闭当前 ...

  5. java同一个类中,构造器如何调用另一个重载的构造器?

    构造器里面调用其它构造器,格式方法如下:1.使用this调用另一个重载构造器,只能在构造器中使用:2.必须写在构造器执行体的第一行语句: 示例如下: import static java.lang.S ...

  6. 数据挖掘算法以及其实现zz

    实验一    分类技术及其应用 实习要求: 基于线性回归模型拟合一个班学生的学习成绩,建立预测模型.数据可由自己建立100个学生的学习成绩. 1)    算法思想: 最小二乘法 设经验方程是y=F(x ...

  7. IntelliJ IDEA 2017版 导入maven项目需要的包

    1.选中项目,鼠标右键--->maven---->Reimport

  8. Thrift线程和状态机分析

    目录 目录 1 1. 工作线程和IO线程 1 2. TNonblockingServer::TConnection::transition() 2 3. RPC函数被调用过程 3 4. 管道和任务队列 ...

  9. 20155334 2016-2017-2 《Java程序设计》第六周学习总结

    20155334 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 第十章:输入/输出 InputStream与OutputStream java将输入/输出抽 ...

  10. HDU1875 畅通工程再续 2017-04-12 19:52 48人阅读 评论(0) 收藏

    畅通工程再续 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submis ...