浅谈线段树合并:https://www.cnblogs.com/AKMer/p/10251001.html

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

离线,按照权值排序之后就跟[HNOI2012]永无乡一样了。

时间复杂度:\(O(nlogn)\)

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

代码如下:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn=1e5+5,maxm=5e5+5; int n,m,Q,cnt;
int tmp[maxn],h[maxn];
int fa[maxn],rt[maxn],ans[maxm]; 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;
} struct edge {
int a,b,v; bool operator<(const edge &a)const {
return v<a.v;
}
}e[maxm]; struct Query {
int u,rk,limit,id; bool operator<(const Query &a)const {
return limit<a.limit;
}
}q[maxm]; int find(int x) {
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
} struct segment_tree {
int tot;
int sum[maxn*20],ls[maxn*20],rs[maxn*20]; void change(int &p,int l,int r,int pos) {
p=++tot,sum[p]=1;
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)change(ls[p],l,mid,pos);
else change(rs[p],mid+1,r,pos);
} int merge(int a,int b) {
if(!a||!b)return a+b;
if(!ls[a]&&!rs[a]&&!ls[b]&&!rs[b]) {
sum[a]+=sum[b];return a;
}
ls[a]=merge(ls[a],ls[b]);
rs[a]=merge(rs[a],rs[b]);
sum[a]=sum[ls[a]]+sum[rs[a]];
return a;
} int query(int p,int l,int r,int rk) {
if(l==r)return l;
int mid=(l+r)>>1;
if(sum[rs[p]]>=rk)return query(rs[p],mid+1,r,rk);
else return query(ls[p],l,mid,rk-sum[rs[p]]);
}
}T; int main() {
n=read(),m=read(),Q=read();
for(int i=1;i<=n;i++)
tmp[i]=h[i]=read();
sort(tmp+1,tmp+n+1);
cnt=unique(tmp+1,tmp+n+1)-tmp-1;
for(int i=1;i<=n;i++)
h[i]=lower_bound(tmp+1,tmp+cnt+1,h[i])-tmp;
for(int i=1;i<=m;i++)
e[i].a=read(),e[i].b=read(),e[i].v=read();
for(int i=1;i<=Q;i++)
q[i].u=read(),q[i].limit=read(),q[i].rk=read(),q[i].id=i;
sort(e+1,e+m+1),sort(q+1,q+Q+1);
for(int i=1;i<=n;i++)
fa[i]=i,T.change(rt[i],1,cnt,h[i]);
int st=1;
for(int i=1;i<=Q;i++) {
while(st<=m&&e[st].v<=q[i].limit) {
int a=find(e[st].a),b=find(e[st].b);
if(a!=b)fa[a]=b,rt[b]=T.merge(rt[b],rt[a]);st++;
}
int u=find(q[i].u);
if(T.sum[rt[u]]<q[i].rk)ans[q[i].id]=-1;
else ans[q[i].id]=tmp[T.query(rt[u],1,cnt,q[i].rk)];
}
for(int i=1;i<=Q;i++)
printf("%d\n",ans[i]);
return 0;
}

最新文章

  1. 闲来无事,写个基于TCP协议的Socket通讯Demo
  2. UVALive 4949 Risk(二分网络流、SAP)
  3. [php] PHP Fatal error: Class &#39;AMQPConnection&#39; not found
  4. exploring the http Object
  5. JVM——类加载机制
  6. oracle 行转列 分析函数
  7. 【转】ArrayList的toArray,也就是list.toArray[new String[list.size()]];,即List转为数组
  8. Ruby on Rails创始人DHH谈如何进行混合移动APP开发
  9. C#高级知识点概要(1) - 委托和事件
  10. maven pom.xml 中各个标签元素的作用
  11. ●BOZJ 4456 [Zjoi2016]旅行者
  12. 线程池、进程池(concurrent.futures模块)和协程
  13. 18.7 修改IP地址
  14. Oracle的简单的创建dblink以及进行数据迁移的方法
  15. ubuntu: firefox+flashplay
  16. pandas重置索引的几种方法探究
  17. jquery 滑动取值
  18. python值传递和指针传递
  19. PAT 乙级 1037 在霍格沃茨找零钱(20)C++版
  20. java8时间使用小结

热门文章

  1. dubbo启动报错多个资源争缓存问题
  2. oracle 如何完全删除干净
  3. Delphi窗体研究,留个爪,以后回来研究
  4. Apache Shiro 使用手册(四)Realm 实现(转发:http://kdboy.iteye.com/blog/1169631)
  5. vim中设置tab的长度的方法
  6. LeetCode:完全平方数【279】【DP】
  7. UVA - 10870 Recurrences 【矩阵快速幂】
  8. elk示例-精简版2
  9. 新手用的git配置命令
  10. C++的动态库和静态库(dll)