题目链接:点击查看

题目大意:有 n 座山峰,每座山峰有他的高度 h[ i ] ,有些山峰之间有双向道路相连,共 m 条路径,每条路径有一个困难值,这个值越大表示越难走。

现在有 q 组询问,每组询问询问从点 v 开始只经过困难值小于等于 x 的路径所能到达的山峰中第 k 高的山峰,如果无解输出 −1。

题目分析:因为有困难值的限制,所以可以对整个图跑克鲁斯卡尔重构树,如果对点 v 来说,只能走小于等于 x 的路径,可以树上倍增找到权值小于等于 x 的,深度最浅的祖先,显然这个祖先子树中的所有点都是可以从点 v 到达的,接下来找第 k 小,就是主席树的工作了,dfs 序上建一下主席树就好了

注意,题目中需要求的是第 k 大,而不是第 k 小

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;int h[N],f[N],val[N],dp[N][25],L[N],R[N],n,nn,m,q,tot,limit;bool vis[N];
/*主席树*/
struct Node
{int l,r;int sum;
}tree[N*20];int cnt,root[N];void init()
{root[0]=0;tree[0].l=tree[0].r=tree[0].sum=0;cnt=1;
}void update(int num,int &k,int l,int r)
{tree[cnt++]=tree[k];k=cnt-1;tree[k].sum++;if(l==r)return;int mid=l+r>>1;if(num<=mid)update(num,tree[k].l,l,mid);elseupdate(num,tree[k].r,mid+1,r);
}int query(int i,int j,int k,int l,int r)//i:左端点根节点编号,j:右端点根节点编号,k:第k大的数,l,r:区间[l,r]
{int d=tree[tree[j].r].sum-tree[tree[i].r].sum;if(l==r)return l;int mid=l+r>>1;if(k<=d)return query(tree[i].r,tree[j].r,k,mid+1,r);elsereturn query(tree[i].l,tree[j].l,k-d,l,mid);
}
/*主席树*/
struct Edge
{int u,v,w;bool operator<(const Edge& t)const{return w<t.w;}
}edge[N];vector<int>node[N];//邻接表
/*dfs序+树上倍增*/
void dfs(int u,int fa)
{vis[u]=true;dp[u][0]=fa;for(int i=1;i<=limit;i++)dp[u][i]=dp[dp[u][i-1]][i-1];L[u]=++tot;root[tot]=root[tot-1];if(u<=n)update(h[u],root[tot],1,nn);for(auto v:node[u])dfs(v,u);R[u]=tot;
}
/*dfs序+树上倍增*/
/*并查集+克鲁斯卡尔重构树*/
int find(int x)
{return f[x]==x?x:f[x]=find(f[x]);
}void Ex_Kruskal()
{int index=n;for(int i=1;i<=n<<1;i++)f[i]=i;sort(edge+1,edge+1+m);for(int i=1;i<=m;i++){int xx=find(edge[i].u),yy=find(edge[i].v);if(xx!=yy){f[xx]=f[yy]=++index;val[index]=edge[i].w;node[index].push_back(xx);node[index].push_back(yy);}}
}
/*并查集+克鲁斯卡尔重构树*/
/*离散化*/
vector<int>disc;void discreate()
{sort(disc.begin(),disc.end());disc.erase(unique(disc.begin(),disc.end()),disc.end());nn=disc.size();for(int i=1;i<=n;i++)h[i]=lower_bound(disc.begin(),disc.end(),h[i])-disc.begin()+1;
}
/*离散化*/
int get_pos(int u,int up)//树上倍增找满足的祖先
{for(int i=20;i>=0;i--)if(dp[u][i]!=0&&val[dp[u][i]]<=up)u=dp[u][i];return u;
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);init();scanf("%d%d%d",&n,&m,&q);limit=log2(n)+1;for(int i=1;i<=n;i++){scanf("%d",h+i);disc.push_back(h[i]);}discreate();for(int i=1;i<=m;i++)scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);Ex_Kruskal();for(int i=1;i<=n;i++)if(!vis[i])dfs(find(i),0);while(q--){int v,x,k;scanf("%d%d%d",&v,&x,&k);v=get_pos(v,x);if(tree[root[R[v]]].sum-tree[root[L[v]-1]].sum<k)puts("-1");elseprintf("%d\n",disc[query(root[L[v]-1],root[R[v]],k,1,nn)-1]);}return 0;
}

洛谷 - P4197 Peaks(Kruskal重构树+dfs序+主席树)相关推荐

  1. 【kruskal重构树】【主席树】werewolf 狼人(P4899)

    正题 P4899 题目大意 给你一个图,对于每次询问Si,Ei,Li,RiS_i,E_i,L_i,R_iSi​,Ei​,Li​,Ri​,回答从SiS_iSi​走到EiE_iEi​,是否存在路径满足前面 ...

  2. 2019.03.21【ZJOI2007】【BZOJ1095】【洛谷P2056】Hide 捉迷藏(DFS序)(线段树)

    BZOJ传送门 洛谷传送门 解析: 其实就是QTREE4的弱化版,可以直接用QTREE4的解法来做. 但是这道题有优秀的O(nlog⁡n)O(n\log n)O(nlogn)做法. 我们考虑利用DFS ...

  3. 洛谷 - P3899 [湖南集训]谈笑风生(dfs序+主席树/二维数点)

    题目链接:点击查看 题目大意:设 TTT 为一棵有根树,我们做如下的定义: 设 aaa 和 bbb 为 TTT 中的两个不同节点.如果 aaa 是 bbb 的祖先,那么称"aaa 比 bbb ...

  4. 【IOI2018】狼人【Kruscal重构树】【主席树】

    题意:nnn个点mmm条边的无向图,qqq次询问,每次给定s,t,L,Rs,t,L,Rs,t,L,R,判断是否存在一条sss到ttt的路径,使得路径上可以找到一点kkk,满足此路径s∼ks\sim k ...

  5. 洛谷P4559 [JSOI2018]列队 【70分二分 + 主席树】

    题目链接 洛谷P4559 题解 只会做\(70\)分的\(O(nlog^2n)\) 如果本来就在区间内的人是不用动的,区间右边的人往区间最右的那些空位跑,区间左边的人往区间最左的那些空位跑 找到这些空 ...

  6. 【洛谷 P2633】 Count on a tree(主席树,树上差分)

    题目链接 思维难度0 实现难度7 建出主席树后用两点的状态减去lca和lca父亲的状态,然后在新树上跑第\(k\)小 #include <cstdio> #include <cstr ...

  7. 2021牛客多校7 - xay loves trees(dfs序+主席树-标记永久化)

    题目链接:点击查看 题目大意:给出两棵以点 111 为根节点的有根树,现在要求满足条件的最大集合: 在第一棵树中,集合内的任意两个点都必须满足祖先关系,即 uuu 是 vvv 的祖先或 vvv 是 u ...

  8. nowcoder172C 保护 (倍增lca+dfs序+主席树)

    https://www.nowcoder.com/acm/contest/172/C (sbw大佬太强啦 orz) 先把每一个路径(x,y)分成(x,lca),(y,lca)两个路径,然后就能发现,对 ...

  9. 【BZOJ3439】Kpm的MC密码,trie树+dfs序+主席树

    Time:2016.05.07 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 1.have a trie,还得是倒着建的,记录每个结尾节点的id(可能会有重复,所以开一个vecto ...

最新文章

  1. 多线程下ArrayList类线程不安全的解决方法及原理
  2. python中 .sort()、 sorted()和 .reverse() 、reversed()的区别
  3. toString() 和 强制类型转换 (String)
  4. Js高级(1) 事件11.30
  5. HTML-CSS-JS Prettify报错Node.js was not found 解决方法
  6. 机器学习工程师 - Udacity 强化学习 Part Eleven
  7. “声波识别”可用于购物
  8. SSM高校实验室安全培训系统设计与实现.docx
  9. Proxyee-down – 百度网盘全平台满速下载神器,还带有IDM的全网嗅探功能!(替代PanDownload)
  10. python开启一个简单的服务器
  11. matlab 矩阵增加行,MATLAB 中 如何在矩阵中插入1行
  12. 2021-05-18
  13. 超详细Netty入门
  14. Mac卸载postgresql
  15. Arcgis desktop 10及Arcgis Engine 10破解
  16. 《孩子,为你自己读书》(Yanlz+Unity+SteamVR+云技术+5G+AI+VR云游戏+多多图书馆+志存当高远+读万卷书如行万里路+术业有专攻+读书是对思想的一种升华+立钻哥哥++==)
  17. 获取电脑的 SN 码
  18. 移动电源充电宝新国标GB/T 35590-2017检测报告测试项目
  19. matlab里hold什么isi,Matlab关于图形保持的hold的使用
  20. “一个扫描枪一张表”,韵达选择 TDengine 应对每日亿级数据量

热门文章

  1. windows服务器部署jar包
  2. 计算机在人力资源管理中的应用浅谈,计算机技术在人力资源管理工作中的应用.doc...
  3. 创建springmvc配置
  4. RabbitMQ快速入门--消息模型介绍
  5. AQS.accquire
  6. Redis中的代理Sharding
  7. 点餐业务服务拆分分析
  8. 二叉树的遍历实现-1(三级)
  9. php删除垃圾文件,Python删除windows垃圾文件的方法
  10. FreeSql与SqlSugar性能测试对比