左偏树/斜堆/可并堆-洛谷P3377 【模板】左偏树(可并堆)
2017-03-01 22:56
316 查看
https://www.luogu.org/problem/show?pid=3377
我们知道二叉堆,就是优先队列,那个stl有的,Priority Queues;
这个建议大家去试试手写;
我们知道二叉堆合并很难,时间复杂度高;
那我们怎么搞呢,用更高级的数据结构–可并堆;
先自学一下这个
http://wenku.baidu.com/search?word=%CB%E3%B7%A8%BA%CF%BC%AF%D6%AE%A1%B6%D7%F3%C6%AB%CA%F7%B5%C4%CC%D8%B5%E3%BC%B0%C6%E4%D3%A6%D3%C3%A1%B7&lm=0&od=0&fr=top_home
然后我就没什么好讲的了;
……
但是有些想法还是跟大家说说;
首先我们为什么要让这个堆左边偏大;
这个跟我们合并有关系;
合并时,我们把权值小的根节点的右儿子和权值大的更节点先合并;
所以我们让右边小一点合并速度更快;
对吧(对个屁)
那我们为什么要让 《权值小的根节点的右儿子去合并
而不是 《值大的根节点的右儿子去合并呢?;
因为根节点要最小呀!
那我们为什么是右节点合并而不是左合并,这样右节点深度会更小;
我们让右节点深度小,就是为了让右节点去合并,这样时间复杂度才可以保证啊;
那这时模版代码;
但是我的查询时间是O(log2n);
毕竟我们要找到根节点嘛;
当然可以用路径压缩;
这个是斜对
左偏树(跑得慢??????)
路径压缩(无用,慢)
我们知道二叉堆,就是优先队列,那个stl有的,Priority Queues;
这个建议大家去试试手写;
我们知道二叉堆合并很难,时间复杂度高;
那我们怎么搞呢,用更高级的数据结构–可并堆;
先自学一下这个
http://wenku.baidu.com/search?word=%CB%E3%B7%A8%BA%CF%BC%AF%D6%AE%A1%B6%D7%F3%C6%AB%CA%F7%B5%C4%CC%D8%B5%E3%BC%B0%C6%E4%D3%A6%D3%C3%A1%B7&lm=0&od=0&fr=top_home
然后我就没什么好讲的了;
……
但是有些想法还是跟大家说说;
首先我们为什么要让这个堆左边偏大;
这个跟我们合并有关系;
合并时,我们把权值小的根节点的右儿子和权值大的更节点先合并;
所以我们让右边小一点合并速度更快;
对吧(对个屁)
那我们为什么要让 《权值小的根节点的右儿子去合并
而不是 《值大的根节点的右儿子去合并呢?;
因为根节点要最小呀!
那我们为什么是右节点合并而不是左合并,这样右节点深度会更小;
我们让右节点深度小,就是为了让右节点去合并,这样时间复杂度才可以保证啊;
那这时模版代码;
但是我的查询时间是O(log2n);
毕竟我们要找到根节点嘛;
当然可以用路径压缩;
这个是斜对
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; struct heap{ int xx,yy,vv,fa,; }a[100001]; bool b[100001]; int n,m,x,y,z; int merge(int x,int y){ if(!x)return y; if(!y)return x; if((a[x].vv>a[y].vv)||(a[x].vv==a[y].vv&&x>y))swap(x,y); int f=merge(a[x].yy,y); a[x].yy=a[x].xx; a[x].xx=f; return x; } void dfs(int x,int y){ if(!x)return; a[x].fa=y; dfs(a[x].xx,y); dfs(a[x].yy,y); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i].vv),a[i].fa=i; while(m--){ scanf("%d",&z); if(z==1){ scanf("%d%d",&x,&y); if(b[x]||b[y])continue; int xx=a[x].fa; int yy=a[y].fa; if(xx==yy)continue; int f=merge(xx,yy); dfs(f,f); }else{ scanf("%d",&x); if(b[x]){printf("-1\n");continue;} int xx=a[x].fa; b[xx]=1; printf("%d\n",a[xx].vv); int f=merge(a[xx].xx,a[xx].yy); dfs(f,f); } } } f9cf
左偏树(跑得慢??????)
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; struct heap{ int xx,yy,vv,fa,dist; }a[100001]; bool b[100001]; int n,m,x,y,z; int merge(int x,int y){ if(!x)return y; if(!y)return x; if((a[x].vv>a[y].vv)||(a[x].vv==a[y].vv&&x>y))swap(x,y); int f=merge(a[x].yy,y); a[x].yy=f; if(a[a[x].yy].dist>a[a[x].xx].dist)swap(a[x].xx,a[x].yy); a[x].dist=a[a[x].yy].dist+1; return x; } void dfs(int x,int y){ if(!x)return; a[x].fa=y; dfs(a[x].xx,y); dfs(a[x].yy,y); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i].vv),a[i].fa=i; while(m--){ scanf("%d",&z); if(z==1){ scanf("%d%d",&x,&y); if(b[x]||b[y])continue; int xx=a[x].fa; int yy=a[y].fa; if(xx==yy)continue; int f=merge(xx,yy); dfs(f,f); }else{ scanf("%d",&x); if(b[x]){printf("-1\n");continue;} int xx=a[x].fa; b[xx]=1; printf("%d\n",a[xx].vv); int f=merge(a[xx].xx,a[xx].yy); dfs(f,f); } } }
路径压缩(无用,慢)
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; struct heap{ int xx,yy,vv,fa; }a[100001]; bool b[100001]; int n,m,x,y,z; int merge(int x,int y){ if(!x)return y; if(!y)return x; if((a[x].vv>a[y].vv)||(a[x].vv==a[y].vv&&x>y))swap(x,y); a[x].yy=merge(a[x].yy,y); a[a[x].yy].fa=x; swap(a[x].yy,a[x].xx); return x; } int get(int x){while(a[x].fa!=x)x=a[x].fa;return x;} int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i].vv),a[i].fa=i; while(m--){ scanf("%d",&z); if(z==1){ scanf("%d%d",&x,&y); if(b[x]||b[y])continue; int xx=get(x); int yy=get(y); if(xx==yy)continue; int f=merge(xx,yy); }else{ scanf("%d",&x); if(b[x]){printf("-1\n");continue;} int xx=get(x); b[xx]=1; printf("%d\n",a[xx].vv); a[xx].fa=merge(a[xx].xx,a[xx].yy); a[a[xx].fa].fa=a[xx].fa; } } }
相关文章推荐
- 模板 可并堆【洛谷P3377】 【模板】左偏树(可并堆)
- 【洛谷P3377】【模板】左偏树(可并堆)
- 洛谷P3377 【模板】左偏树(可并堆)
- 左偏树 模板
- 左偏树模板【pascal】
- 左偏树,原理及模板
- 左偏树模板
- 【模板】左偏树
- 左偏树 模板
- P3377 【模板】左偏树(可并堆)
- [Luogu3377]【模板】左偏树(可并堆)
- 洛谷3377【【模板】左偏树】--左偏树&并查集
- 左偏树简介(洛谷P3377题解)
- 左偏树模板
- ZOJ2334 Monkey King 【左偏树模板题】
- luogu3377【模板】左偏树(可并堆)
- HDU3031及左偏树模板
- 左偏树模板
- ACM 左偏树(模板)
- luoguP3377 【模板】左偏树(可并堆)