题目链接

\(Description\)

有n个座山,其高度为hi。有m条带权双向边连接某些山。多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少。

\(Solution\)

x的限制将图分成了若干连通块,如果x单调递增的话,只需要合并连通块就可以了。

离线,并查集维护所属连通块,线段树合并状态、查询K大。(强制在线的话可以主席树?BZOJ3551 不想写了还是写了,还好)

强制在线的Kruskal+主席树做法:BZOJ3551

//39360kb	5248ms
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 250000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=1e5+5,M=5e5+5; int n,m,Q,cnt,ref[N],h[N],Ans[M],fa[N],root[N];
char IN[MAXIN],*SS=IN,*TT=IN;
inline int read();
struct Edge{
int fr,to,val;
inline void Read(){
fr=read(), to=read(), val=read();
}
bool operator <(const Edge &a)const{
return val<a.val;
}
}e[M];
struct QUERY{
int fr,x,k,id;
inline void Read(int i){
fr=read(), x=read(), k=read(), id=i;
}
bool operator <(const QUERY &a)const{
return x<a.x;
}
}q[M];
struct Segment_Tree
{
#define S N*18
#define lson son[x][0]
#define rson son[x][1]
int tot,sz[S],son[S][2]; void Insert(int &x,int l,int r,int p)
{
sz[x=++tot]=1;
if(l==r) return;
int m=l+r>>1;
if(p<=m) Insert(lson,l,m,p);
else Insert(rson,m+1,r,p);
}
int Merge(int x,int y)
{
if(!x||!y) return x^y;
lson=Merge(lson,son[y][0]), rson=Merge(rson,son[y][1]);
sz[x]+=sz[y]; /*sz[y]=0;*/ return x;
}
int Query(int x,int l,int r,int k)
{
if(l==r) return l;
int ls=sz[lson];
if(k<=ls) return Query(lson,l,l+r>>1,k);
return Query(rson,(l+r>>1)+1,r,k-ls);
}
}T; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
int Getfa(int x){
return x==fa[x]?x:fa[x]=Getfa(fa[x]);
}
inline int Find(int x)
{
int l=1,r=cnt,mid;
while(l<r)
if(ref[mid=l+r>>1]<x) l=mid+1;
else r=mid;
return l;
}
void Merge(int x,int y)
{
int r1=Getfa(x), r2=Getfa(y);
if(r1==r2) return;
fa[r2]=r1, root[r1]=T.Merge(root[r1],root[r2]);
}
int Query(int x,int k)
{
int rt=Getfa(x);
return T.sz[root[rt]]<k?-1:ref[T.Query(root[rt],1,cnt,T.sz[root[rt]]-k+1)];
} int main()
{
n=read(), m=read(), Q=read();
for(int i=1; i<=n; ++i) ref[i]=h[i]=read(), fa[i]=i;
std::sort(ref+1,ref+1+n), cnt=1;
for(int i=2; i<=n; ++i) if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
for(int i=1; i<=n; ++i) h[i]=Find(h[i]), T.Insert(root[i],1,cnt,h[i]); for(int i=1; i<=m; ++i) e[i].Read();
std::sort(e+1,e+1+m);
for(int i=1; i<=Q; ++i) q[i].Read(i);
std::sort(q+1,q+1+Q); for(int i=1,now=1; i<=Q; ++i)
{
while(now<=m && e[now].val<=q[i].x) Merge(e[now].fr,e[now].to), ++now;
Ans[q[i].id]=Query(q[i].fr,q[i].k);
}
for(int i=1; i<=Q; ++i) printf("%d\n",Ans[i]); return 0;
}

2019.11.15:

//39404kb	5876ms 跑的又比以前慢自闭了
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
//#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5,M=5e5+5; int ref[N],h[N],Ans[M],root[N],fa[N];
//char IN[MAXIN],*SS=IN,*TT=IN;
struct Edge
{
int u,v,w;
bool operator <(const Edge &x)const
{
return w<x.w;
}
}e[M];
struct Queries
{
int s,v,k,id;
bool operator <(const Queries &x)const
{
return v<x.v;
}
}q[M];
struct Segment_Tree
{
#define S N*18
#define ls son[x][0]
#define rs son[x][1]
#define lson ls,l,l+r>>1
#define rson rs,(l+r>>1)+1,r
int tot,son[S][2],sz[S];
#undef S void Insert(int &x,int l,int r,int p)
{
sz[x=++tot]=1;
if(l<r) p<=(l+r>>1) ? Insert(lson,p) : Insert(rson,p);
}
int Merge(int x,int y)
{
if(!x||!y) return x|y;
ls=Merge(ls,son[y][0]), rs=Merge(rs,son[y][1]);
return sz[x]+=sz[y],x;
}
int Query(int x,int l,int r,int k)
{
if(l==r) return l;
int lsz=sz[ls];
return lsz>=k?Query(lson,k):Query(rson,k-lsz);
}
}T; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
int Getfa(int x)
{
return x==fa[x]?x:fa[x]=Getfa(fa[x]);
}
inline int Find(int x,int r)
{
int l=1,mid;
while(l<r)
if(ref[mid=l+r>>1]<x) l=mid+1;
else r=mid;
return l;
}
inline void Merge(int x,int y)
{
int r1=Getfa(x),r2=Getfa(y);
if(r1!=r2) fa[r2]=r1, root[r1]=T.Merge(root[r1],root[r2]);
}
inline int Query(int n,int x,int k)
{
int rt=root[Getfa(x)];
return T.sz[rt]<k?-1:ref[T.Query(rt,1,n,T.sz[rt]-k+1)];
} int main()
{
const int n=read(),m=read(),Q=read();
for(int i=1; i<=n; ++i) ref[i]=h[i]=read();
std::sort(ref+1,ref+1+n); int cnt=1;
for(int i=2; i<=n; ++i) if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
for(int i=1; i<=n; ++i) h[i]=Find(h[i],cnt);
for(int i=1; i<=n; ++i) T.Insert(root[i],1,cnt,h[i]); for(int i=1; i<=m; ++i) e[i]=(Edge){read(),read(),read()};
for(int i=1; i<=Q; ++i) q[i]=(Queries){read(),read(),read(),i};
std::sort(e+1,e+1+m), std::sort(q+1,q+1+Q); for(int i=1; i<=n; ++i) fa[i]=i;
e[m+1].w=2e9;
for(int i=1,now=1; i<=Q; ++i)
{
while(e[now].w<=q[i].v) Merge(e[now].u,e[now].v), ++now;
Ans[q[i].id]=Query(cnt,q[i].s,q[i].k);
}
for(int i=1; i<=Q; printf("%d\n",Ans[i++])); return 0;
}

BZOJ.3545.[ONTAK2010]Peaks(线段树合并)的更多相关文章

  1. 【bzoj3545】[ONTAK2010]Peaks 线段树合并

    [bzoj3545][ONTAK2010]Peaks 2014年8月26日3,1512 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路 ...

  2. BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )

    这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...

  3. BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]

    3545: [ONTAK2010]Peaks 题意:带权图,多组询问与一个点通过边权\(\le x\)的边连通的点中点权k大值 又读错题了,输出点一直WA,问的是点权啊 本题加强版强制在线了,那这道题 ...

  4. Peaks 线段树合并

    Peaks 线段树合并 \(n\)个带权值\(h_i\)山峰,有\(m\)条山峰间双向道路,\(q\)组询问,问从\(v_i\)开始只经过\(h_i\le x\)的路径所能到达的山峰中第\(k\)高的 ...

  5. ●BZOJ 3545 [ONTAK2010]Peaks(离线)

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3545 http://www.lydsy.com/JudgeOnline/problem.ph ...

  6. bzoj 4631: 踩气球 线段树合并

    4631: 踩气球 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 265  Solved: 136[Submit][Status][Discuss] ...

  7. BZOJ:5457: 城市(线段树合并)(尚待优化)

    5457: 城市 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 18  Solved: 12[Submit][Status][Discuss] Des ...

  8. bzoj3545 Peaks 线段树合并

    离线乱搞... 也就是一个线段树合并没什么 #include<algorithm> #include<iostream> #include<cstring> #in ...

  9. bzoj 3545: [ONTAK2010]Peaks

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1124  Solved: 304[Submit][Status][Discuss] Descripti ...

随机推荐

  1. MFC创建线程示例

    MFC创建线程示例 AfxBeginThread() 创建现场的方法是AfxBeginThread()函数. 在[.CPP]文件定义一个全局变量,决定什么时候退出这个线程. BOOL g_bWillE ...

  2. nRFgo Studio 和 Nrfjprog 无法找到JLinkARM.dll的解决方法

    Segger在第一次安装的时候,会在注册表中添加安装路径的字段,nRF的两个软件就根据这两个注册表字段来寻找JLinkARM.dll.而当你卸载/更新Segger的时候,注册表的相关的字段是不会被修改 ...

  3. NandFlash和iNand

    nand 1.nand的单元组织:block与page(大页Nand与小页Nand)(1)Nand的页和以前讲过的块设备(尤其是硬盘)的扇区是类似的.扇区最早在磁盘中是512字节,后来也有些高级硬盘扇 ...

  4. linux中fork()函数详解【转】

    转自:http://blog.csdn.net/jason314/article/details/5640969 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过 ...

  5. mysql系列七、mysql索引优化、搜索引擎选择

    一.建立适当的索引 说起提高数据库性能,索引是最物美价廉的东西了.不用加内存,不用改程序,不用调sql,只要执行个正确的'create index',查询速度就可能提高百倍千倍,这可真有诱惑力.可是天 ...

  6. Linux安全配置步骤简述

    一.磁盘分区  1.如果是新安装系统,对磁盘分区应考虑安全性:   1)根目录(/).用户目录(/home).临时目录(/tmp)和/var目录应分开到不同的磁盘分区:   2)以上各目录所在分区的磁 ...

  7. 【Android开发】之Fragment与Acitvity通信

    上一篇我们讲到与Fragment有关的常用函数,既然Fragment被称为是“小Activity”,现在我们来讲一下Fragment如何与Acitivity通信.如果上一篇还有不懂得,可以再看一下.传 ...

  8. ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061),mysql服务已启动

    1 前言 在mysql服务已启动,用命令行进入或者heidisql工具都提示ERROR 2003 (HY000): Can't connect to MySQL server on 'localhos ...

  9. python文件、文件夹操作OS模块

    转自:python文件.文件夹操作OS模块   '''一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法.1.得到当前工作目录,即当前Python脚本工作的目录路径: ...

  10. python下图像读取方式以及效率对比

    https://zhuanlan.zhihu.com/p/30383580 opencv速度最快,值得注意的是mxnet的采用多线程读取的方式,可大大加速