HDU - 3804 Query on a tree(主席树维护最大值+离散化)
题目链接:点击查看
题目大意:给出一棵树,每条边上都有一个权值,给出m个查询:a,b:问从点1到点a的唯一路径上,在边权小于等于b的边中选出边权最大的值输出,若没有符合条件的边则输出-1;
题目分析:时隔三个月再次重温这个题目,感觉这个题目真的就简单多了,直接剖完然后离线线段树做就行了,所以为了挑战一下自己,我选择用主席树写了一发,不得不说,这个题目内存卡的真死,权值的数据给到了1e9,本来想开32倍的主席树然后直接用线段树动态离散化的,结果第一发直接MLE了,看了一眼题目给的内存,只给了32M,开32倍的线段树就直接38M了,无奈,只能离散化一下了,还好这个题没卡我用vector离散化,最后31.7M险些飘过
这里和zx学长在讨论这个题的时候有点对主席树的小理解吧,我之前有点想当然的以为主席树都应该维护一个sum来判断是否有满足条件的区间,但其实并不然,就拿这个题为例,因为是要求点1到点u这条链上满足条件的最大值,所以我们只用维护一个最大值的主席树即可,并不用维护sum这个变量了,zx学长给我这么一点拨,我就想到若想求u-v这条边上满足条件的最大值的话,是不是就不太好用主席树来做了,zx学长只是给我留了一句话,可以用主席树做,只不过时间复杂度会带上个常数,emmm,说实话我想了很久也没想到该怎么实现,可能是我还太菜了,我现在对主席树的理解还是只会维护一个sum和,然后用sum解决第k大的问题以及大于等于或者小于等于k的数有多少个,要是真的让写从u-v上满足条件的最大值的话,我还是只会卑微的用线段树离线来写
希望过三个月再回顾现在写的这些内容,会感觉自己之前的理解都好幼稚,也希望能看到进步之后的自己,就像现在的自己看三个月之前的博客一样吧
代码:
#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;int n;struct Node
{int to,w,next;
}edge[N<<1];int head[N],tot;void addedge(int u,int v,int w)//链式前向星
{edge[tot].to=v;edge[tot].w=w;edge[tot].next=head[u];head[u]=tot++;edge[tot].to=u;edge[tot].w=w;edge[tot].next=head[v];head[v]=tot++;
}vector<int>num;//离散化蛹int getnum(int x)//离散化用
{return lower_bound(num.begin(),num.end(),x)-num.begin()+1;
}struct tree
{int l,r,mmax;
}tree[N*32];//主席树维护最大值int root[N],cnt;void insert(int pre,int& cur,int l,int r,int pos)
{cur=++cnt;tree[cur]=tree[pre];tree[cur].mmax=max(tree[pre].mmax,pos);if(l==r)return;int mid=l+r>>1;if(mid>=pos)insert(tree[pre].l,tree[cur].l,l,mid,pos);elseinsert(tree[pre].r,tree[cur].r,mid+1,r,pos);
}int query(int cur,int l,int r,int ll,int rr)//l,r:当前区间 ll,rr:目标区间
{if(l>=ll&&r<=rr)return tree[cur].mmax;if(r<ll||l>rr)return 0;int mid=l+r>>1;return max(query(tree[cur].l,l,mid,ll,rr),query(tree[cur].r,mid+1,r,ll,rr));
}void dfs(int u,int f)
{for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;if(v==f)continue;insert(root[u],root[v],1,num.size(),getnum(w));dfs(v,u);}
}void init()
{for(int i=1;i<=n;i++)head[i]=-1;cnt=tot=0;
}int main()
{
// freopen("input.txt","r",stdin);
// ios::sync_with_stdio(false);int w;cin>>w;while(w--){scanf("%d",&n);init();num.clear();for(int i=1;i<n;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);addedge(u,v,w);num.push_back(w);}sort(num.begin(),num.end());num.erase(unique(num.begin(),num.end()),num.end());dfs(1,0);int m;scanf("%d",&m);while(m--){int x,y;scanf("%d%d",&x,&y);int pos=upper_bound(num.begin(),num.end(),y)-num.begin();int ans=query(root[x],1,num.size(),1,pos);if(ans)printf("%d\n",num[ans-1]);elseprintf("%d\n",-1);}}return 0;
}
HDU - 3804 Query on a tree(主席树维护最大值+离散化)相关推荐
- HDU - 3804 Query on a tree(树链剖分+线段树+离线处理)
题目链接:点击查看 题目大意:给出一棵树,每条边上都有一个权值,给出m个查询:a,b:问从点1到点a的唯一路径上,在边权小于等于b的边中选出边权最大的值输出,若没有符合条件的边则输出-1: 题目分析: ...
- SPOJ 10628 Count on a tree 主席树 附数据生成器
很奇怪的题啊,感觉思路和别人一样,但是我得用快速IO才能AC--不然就T 没用快速output,只用了快速input 而且居然限制代码长度...代码要短于6000B,我改了好久啊 题目大意:给一棵树, ...
- CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度
题意描述 有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\).求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模). 题解 思路很简单--用主 ...
- hdu 4605 Magic Ball Game (在线主席树/离线树状数组)
版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4605 题意: 有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi .然后,有一个球,附带值x . 球 ...
- HDU - 6704 K-th occurrence (后缀数组+主席树)
题目链接 题意 QQQ次询问,每次询问求SSS的子串出现KKK次的位置 思路 刚开始想的是AC自动机,但是建自动机会超时,后来学长想到后缀数组+主席树的做法Orz...Orz...Orz... 出现K ...
- SPOJ 375. Query on a tree (树链剖分)
题目链接: http://www.spoj.com/problems/QTREE/ 375. Query on a tree Problem code: QTREE You are given a t ...
- XXI Open Cup. Grand Prix of Korea I. Query On A Tree 17 树剖 + 二分 + 树带权重心
传送门 文章目录 题意: 思路: 题意: 给你一棵树,每棵树初始权值都为000,现在给你两个操作: (1)(1)(1)将uuu的子树权值全部加111. (2)(2)(2)将(u,v)(u,v)(u,v ...
- bzoj2588: Spoj 10628. Count on a tree 主席树
在每一个点的父亲做主席树,每次访问时用两个点的和减去其LCA和LCA父亲的和即可. #include<bits/stdc++.h> using namespace std; inline ...
- HDU 4348 To the moon(主席树区间修改)
题意 给你一个区间,支持如下操作: 在一段区间内加上一个值,并生成一个历史版本 查询某个版本下一段区间内的和 回到一个历史版本上并舍弃之后的版本 做法 这就是主席树区间修改裸题啦QwQ 上一篇博客我讲 ...
最新文章
- cli vue 卸载,vue Cli 环境删除与重装教程 - 版本文档
- s3 aws_您需要了解的有关AWS S3的所有信息
- SQL语言之子查询(Oracle)
- php合同在线签约功能_【市场在线】杭汽辅机实现海外发电市场重大突破 —成功签约阿联酋Fujairah F3 IPP项目表冷器合同...
- 在php中页面布局 3列左右侧固定中间自适应居中,css三列布局--两边固定中间自适应和中间固定两边自适应...
- flask 知识点总结
- 深入理解InnoDB(5)-文件系统
- 启动马达接线实物图_东元伺服驱动马达
- python画猫和老鼠_观察者模式(猫与老鼠的故事!)
- HttpClient 入门与正确使用姿势
- mysql没有索引删除一亿数据_mysql数据库如何实现亿级数据快速清理
- 阿里云云计算 52在线实验--云监控初体验
- bzoj3514 Codechef MARCH14 GERALD07加强版 lct预处理+主席树
- chrome怎么安装java插件下载_java插件下载如何将JAVA插件支持Chrome
- 调用python-nmap实现扫描局域网存活主机
- 翻译来自HiDDeN网络架构-Lifeifei
- edg击败we视频_edg击败we视频_LPL夏季赛:EDG零封V5获三连胜 OMG2-1击败WE
- mysql 常用函数
- Dream-hacking 造梦工程与脑波艺术
- Discuz 论坛优化