zoj 2334
2015-08-11 23:12
218 查看
可并堆,左偏树,这是神犇“顺手学的东西”
以下是左偏树的合并操作代码。
这个题还是比较直白的。。。
时间复杂度:O(m∗log2n)O(m*log_2n)
以下是左偏树的合并操作代码。
int merge(int x,int y) { //p[i] 结点i的权值,这里是维护大根堆 //d[i] 在i的子树中,i到右叶子结点的最远距离. if(!x) return y; if(!y) return x; if(p[x] < p[y]) std::swap(x, y); r[x] = merge(r[x], y); if(r[x]) fa[r[x]] = x; if(d[l[x]] < d[r[x]]) std::swap(l[x], r[x]);//调整树的结构,使其满足左偏性质 d[x] = d[r[x]] + 1; return x; }
这个题还是比较直白的。。。
时间复杂度:O(m∗log2n)O(m*log_2n)
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <string> #include <map> #include <vector> #include <stack> #include <queue> #include <utility> #include <iostream> #include <algorithm> template<class Num>void read(Num &x) { char c; int flag = 1; while((c = getchar()) < '0' || c > '9') if(c == '-') flag *= -1; x = c - '0'; while((c = getchar()) >= '0' && c <= '9') x = (x<<3) + (x<<1) + (c-'0'); x *= flag; return; } template<class Num>void write(Num x) { if(x < 0) putchar('-'), x = -x; static char s[20];int sl = 0; while(x) s[sl++] = x%10 + '0',x /= 10; if(!sl) {putchar('0');return;} while(sl) putchar(s[--sl]); } const int maxn = 1e5 + 50 , maxm = maxn, Nya = -1; int n, m, p[maxn]; int l[maxn], r[maxn], fa[maxn], d[maxn]; void init() { memset(l, 0, sizeof(l)); memset(r, 0, sizeof(r)); memset(fa, 0, sizeof(fa)); memset(d, 0, sizeof(d)); for(int i = 1; i <= n; i++) read(p[i]); read(m); } int merge(int x,int y) { if(!x) return y; if(!y) return x; if(p[x] < p[y]) std::swap(x, y); r[x] = merge(r[x], y); if(r[x]) fa[r[x]] = x; if(d[l[x]] < d[r[x]]) std::swap(l[x], r[x]); d[x] = d[r[x]] + 1; return x; } int root(int x) { while(fa[x]) x = fa[x]; return x; } int dec(int t) { int L = l[t], R = r[t]; fa[L] = fa[R] = 0; l[t] = r[t] = d[t] = 0; p[t] >>= 1; return merge(merge(L, R), t); } void solve() { int u, v, ans; d[0] = Nya; while(m--) { read(u), read(v); u = root(u), v = root(v); ans = (u == v) ? Nya : p[merge(dec(u), dec(v))]; write(ans), puts(""); } } int main() { #ifndef ONLINE_JUDGE freopen("2334.in","r",stdin); freopen("2334.out","w",stdout); #endif while(scanf("%d", &n) != EOF) init(), solve(); #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); #endif return 0; }
相关文章推荐
- The shortest problem(hdu5373+11的倍数)
- zoj 2334 分类: zoj templates 2015-08-11 23:12 2人阅读 评论(0) 收藏
- C++与C#互调dll的实现步骤
- 归档告警频繁监控脚本
- ViewPager
- 我的前端学习笔记 box-sizing,calc,回调函数
- Java小游戏之打飞机(二)
- C++嵌入Python语言(一):环境搭建及HelloWord程序测试
- 第一百三十一天 how can I 坚持
- IOS 30多个iOS常用动画,带详细注释
- BZOJ 1877: [SDOI2009]晨跑( 最小费用最大流 )
- Maven Web项目构建
- FragmentTabHost
- 通过顶点颜色,制作高级贴图混合效果····
- HDU 1863 畅通工程
- 用条件变量来解决生产者消费者问题
- scala的list源码解密
- jQuery版感应鼠标显示隐藏的菜单
- Linux学习笔记:常用命令总结
- Android解惑 - 为什么要用Fragment.setArguments(Bundle bundle)来传递参数(转)