hdu 3804树链剖分+离线操作
/*
树链刨分+离线操作
题意:给你一棵树,和询问x,y
从节点x--节点1的小于等于y的最大值.
解:先建一个空树,将树的边权值从小到大排序,将询问y按从小到大排序
对于每次询问y将小于等于y的边权值的边加入,在进行询问将结果储存最后输出即可
易错点:要考虑到节点1到节点1的情况需特判。
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 110000
#define inf 0x3fffffff
int f[N];
int top[N];
int fa[N];
int siz[N];
int nu,yong;
int head[N];
int deep[N];
int son[N];
int w[N];
int Max;
struct node
{
int u,v,w,next,we;
} bian[N*4],ff[N],fy[N];
void init()
{
yong=nu=0;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
}
void addedge(int u,int v,int w)
{
bian[yong].u=u;
bian[yong].v=v;
bian[yong].w=w;
bian[yong].next=head[u];
head[u]=yong++;
}
void dfs(int u,int father,int d)
{
deep[u]=d;
fa[u]=father;
siz[u]=1;
int i;
for(i=head[u]; i!=-1; i=bian[i].next)
{
int v=bian[i].v;
if(v!=father)
{
dfs(v,u,d+1);
siz[u]+=siz[v];
if(son[u]==-1||siz[son[u]]<siz[v])
son[u]=v;
}
}
return ;
}
void getnu(int u,int cnt)
{
f[u]=nu++;
top[u]=cnt;
if(son[u]==-1)return ;
getnu(son[u],cnt);
int i;
for(i=head[u]; i!=-1; i=bian[i].next)
{
int v=bian[i].v;
if(v!=son[u]&&v!=fa[u])
getnu(v,v);
}
return ;
}
int cmp(const void *a,const void *b)
{
return (*(struct node *)a).v-(*(struct node *)b).v;
}
int cmpp(const void *a,const void *b)
{
return (*(struct node *)a).w-(*(struct node *)b).w;
}
struct nodee
{
int l,r,maxx;
} tree[N*4];
int Ma(int v,int vv)
{
return v>vv?v:vv;
}
void pushup(int t)
{
tree[t].maxx=Ma(tree[t*2].maxx,tree[t*2+1].maxx);
}
void build(int t,int l,int r)
{
tree[t].l=l;
tree[t].r=r;
if(tree[t].l==tree[t].r)
{
tree[t].maxx=-1;
return ;
}
int mid=(tree[t].l+tree[t].r)/2;
build(t*2,l,mid);
build(t*2+1,mid+1,r);
pushup(t);
}
void update(int t,int x,int y)
{
if(tree[t].l==x&&tree[t].r==x)
{
tree[t].maxx=y;
return ;
}
int mid=(tree[t].l+tree[t].r)/2;
if(x<=mid)update(t*2,x,y);
else
update(t*2+1,x,y);
pushup(t);
}
void qury(int t,int l,int r)
{
if(tree[t].l==l&&tree[t].r==r)
{
Max=Ma(Max,tree[t].maxx);
return ;
}
int mid=(tree[t].l+tree[t].r)/2;
if(r<=mid)qury(t*2,l,r);
else if(l>mid)qury(t*2+1,l,r);
else
{
qury(t*2,l,mid);
qury(t*2+1,mid+1,r);
}
pushup(t);
}
int findmax(int u,int v)
{
if(u==v)return -1;//特判因为可能出现节点1到节点1的情况是不存在的
int f1=top[u];
int f2=top[v];
int ans=-inf;
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
Max=-inf;
qury(1,f[f1],f[u]);
ans=Ma(ans,Max);
u=fa[f1];
f1=top[u];
}
if(u==v)return ans;
if(deep[u]>deep[v]) swap(u,v);
Max=-inf;
qury(1,f[son[u]],f[v]);
ans=Ma(ans,Max);
return ans;
}
int main()
{
int n,i,j,k,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init();
for(i=1; i<n; i++)
{
scanf("%d%d%d",&ff[i].u,&ff[i].v,&ff[i].w);
addedge(ff[i].u,ff[i].v,ff[i].w);
addedge(ff[i].v,ff[i].u,ff[i].w);
}
dfs(1,1,0);//得到deep,fa,siz,son数组值
getnu(1,1);//得到f,top的值
for(i=1; i<n; i++)
{
if(deep[ff[i].u]<deep[ff[i].v])
swap(ff[i].u,ff[i].v);
w[ff[i].u]=ff[i].w;
}
build(1,1,nu-1);//建空树
scanf("%d",&k);
for(i=1; i<=k; i++)
{
scanf("%d%d",&fy[i].u,&fy[i].v);
fy[i].w=i;//记录下标
}
qsort(fy+1,k,sizeof(fy[0]),cmp);//排序
qsort(ff+1,n-1,sizeof(ff[0]),cmpp);
for(i=1,j=1; i<=k; i++)
{
for(; j<n;)
{
if(fy[i].v>=ff[j].w)
update(1,f[ff[j].u],ff[j].w);//加边
else break;
j++;
}
fy[i].we=findmax(1,fy[i].u);//查找
}
qsort(fy+1,k,sizeof(fy[0]),cmpp);//再次按下标排序
for(i=1; i<=k; i++)//输出
printf("%d\n",fy[i].we);
}
return 0;
}
hdu 3804树链剖分+离线操作的更多相关文章
- hdu 3804 树链剖分
思路:将边权排序,然后插入线段树,这样就可以直接用二分查找确定答案. #pragma comment(linker, "/STACK:1024000000,1024000000") ...
- hdu 5893 (树链剖分+合并)
List wants to travel Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/O ...
- hdu 5052 树链剖分
Yaoge’s maximum profit Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/ ...
- hdu 4897 树链剖分(重轻链)
Little Devil I Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- hdu 5274 树链剖分
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- HDU 3966 (树链剖分+线段树)
Problem Aragorn's Story (HDU 3966) 题目大意 给定一颗树,有点权. 要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值. 解题分析 树链剖分模板 ...
- hdu 3966(树链剖分+线段树区间更新)
传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...
- HDU 3966 /// 树链剖分+树状数组
题意: http://acm.hdu.edu.cn/showproblem.php?pid=3966 给一棵树,并给定各个点权的值,然后有3种操作: I x y z : 把x到y的路径上的所有点权值加 ...
- hdu 4729 树链剖分
思路:这个树链剖分其实还是比较明显的.将边按权值排序后插入线段树,然后用线段树查找区间中比某个数小的数和,以及这样的数的个数.当A<=B时,就全部建新的管子. 对于A>B的情况比较 建一条 ...
随机推荐
- poj 1286 Necklace of Beads【polya定理+burnside引理】
和poj 2409差不多,就是k变成3了,详见 还有不一样的地方是记得特判n==0的情况不然会RE #include<iostream> #include<cstdio> us ...
- bzoj 1651: [Usaco2006 Feb]Stall Reservations 专用牛棚【贪心+堆||差分】
这个题方法还挺多的,不过洛谷上要输出方案所以用堆最方便 先按起始时间从小到大排序. 我用的是greater重定义优先队列(小根堆).用pair存牛棚用完时间(first)和牛棚编号(second),每 ...
- P3043 [USACO12JAN]牛联盟Bovine Alliance(并查集)
P3043 [USACO12JAN]牛联盟Bovine Alliance 题目描述 Bessie and her bovine pals from nearby farms have finally ...
- 阿里云短信验证_基于阿里云OpenAPI实现
阿里云短信服务 背景简介: 短信验证以及短信通知,目前已经应用的非常广泛,最近因项目需要,需要将原来的短信接口换成阿里云的的短信服务,原项目集成的短信服务能够实现短信的发送以及短信的验证整个过程,简单 ...
- Nginx(一) 安装基于centos7
1. nginx介绍 1.1. 什么是nginx Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.由俄罗斯的程序设计师Igor Sysoev所开 ...
- JavaScript编程艺术-第10章-10.2-实用的动画
10.2-实用的动画 ***代码亲测可用*** HTML: <!DOCTYPE HTML> <html> <head> <meta charset=" ...
- 数学 Codeforces Round #219 (Div. 2) B. Making Sequences is Fun
题目传送门 /* 数学:这题一直WA在13组上,看了数据才知道是计算cost时超long long了 另外不足一个区间的直接计算个数就可以了 */ #include <cstdio> #i ...
- A Python example for HiveServer2
要做一个通过调用python来实现对hive server2 的连接.在网上搜索了很多资料,有些说的hive sever的,但是由于认证方式发生改变,行不通. 最后,找到了权威的说明(PS: 还是应该 ...
- [ CodeForces 1059 D ] Nature Reserve
\(\\\) \(Description\) 你现在有\(N\)个分布在二维平面上的整点\((x_i,y_i)\),现在需要你找到一个圆,满足: 能够覆盖所有的给出点 与\(x\)轴相切 现在需要你确 ...
- [Windows Server 2008] MySQL单数据库迁移方法
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:MySQL ...