SPOJ1487. Query on a tree III 树链剖分+主席树
来源:互联网 发布:网络课程的内容有哪些 编辑:程序博客网 时间:2024/06/06 19:06
思路还是不太难的,只是我没想到。。。就是把点映射到数列上(就是剖分),然后求区间第K大(同一棵子树在数列上的位置总是连续的,所以把树链剖分看成一种特殊的hash)。
限制十分坑爹,在spoj上时间限制很紧,原先写主席树TLE了。后来去bzoj上提交,然后MLE了(spoj空间256M,bzoj只有64M),只能不断地删掉没用的数组,然后重复用,所以代码写得很乱。不过在bzoj上AC之后,在spoj上竟然也AC了(我没有优化时间啊),果真坑爹。
感觉主席树的常数和空间都有点大,不知道需不需要学学划分树。
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>#include <algorithm>#define MIN(a,b) ((a<b)?a:b)#define MAX(a,b) ((a>b)?a:b)#define MEM(a) memset(a,0,sizeof(a))#define mid ((l+r)>>1)using namespace std;const int MAXN = 100010;const int MAXM = 2011110;const int INF = 999999999;int f[MAXN], son[MAXN], s[MAXN], h[MAXN], w[MAXN], v[MAXN];int Time;int root[MAXN], tr[MAXM], ch[MAXM][2];struct edge{int u, next;}e[MAXN << 1];int head[MAXN], nume, numn;inline void addedge(int x, int u){e[++nume].u = u;e[nume].next = head[x];head[x] = nume;}void dfs1(int c){s[c] = 1;for (int i = head[c]; i; i = e[i].next){if (e[i].u != f[c]){f[e[i].u] = c;dfs1(e[i].u);s[c] += s[e[i].u];if (s[e[i].u] > s[son[c]]) son[c] = e[i].u;}}}void dfs2(int c, int tp){h[c] = ++Time; w[Time] = c;if (!son[c]) return;dfs2(son[c], tp);for (int i = head[c]; i; i = e[i].next) if (e[i].u != f[c] && e[i].u != son[c]) dfs2(e[i].u, e[i].u);}void build(int &cx, int &cy, int l, int r, int x){if (!cx) cx = ++numn;if (l == r){tr[cx] = tr[cy] + 1;return;}int m = mid;tr[cx] = tr[cy] + 1;if (x <= m){build(ch[cx][0], ch[cy][0], l, m, x);ch[cx][1] = ch[cy][1];}else{build(ch[cx][1], ch[cy][1], m + 1, r, x);ch[cx][0] = ch[cy][0];}}int query(int cx, int cy, int l, int r, int x){int t = tr[ch[cx][0]] - tr[ch[cy][0]], m = mid;if (l == r) return f[l];if (t >= x) return query(ch[cx][0], ch[cy][0], l, m, x);else return query(ch[cx][1], ch[cy][1], m + 1, r, x - t);}inline bool cmp(edge a, edge b) { return a.u < b.u; }void work(){int i, j, n, t1, t2, t3, tx, ty, t, q, ans;char c[100];Time = nume = numn = 0;scanf("%d", &n);for (i = 1; i <= n; ++i){scanf("%d", &v[i]);e[i].u = v[i]; //离散化,借用边的数组(原先以为会MLE,所以代码写得很乱)e[i].next = i;}sort(e + 1, e + n + 1, cmp); for (i = 1; i <= n; ++i) v[e[i].next] = i;for (i = 1; i < n; ++i){scanf("%d%d", &t1, &t2);addedge(t1, t2);addedge(t2, t1);}scanf("%d", &q);dfs1(1);dfs2(1, 1);for (i = 1; i <= n; ++i) f[v[i]] = i;//f数组用作v的反向索引,输出答案用到for (i = 1; i <= n; ++i) build(root[i], root[i - 1], 1, n, v[w[i]]);//构树for (i = 1; i <= q; ++i){scanf("%d%d", &t1, &t2);printf("%d\n", query(root[h[t1] + s[t1] - 1], root[h[t1] - 1], 1, n, t2));}}int main(){work();return 0;}
0 0
- SPOJ1487. Query on a tree III 树链剖分+主席树
- [主席树] BZOJ 1803 Spoj1487 Query on a tree III
- bzoj 1803: Spoj1487 Query on a tree III(主席树)
- [BZOJ1803]Spoj1487 Query on a tree III(dfs序+主席树)
- BZOJ 1803: Spoj1487 Query on a tree III 主席树题解
- [BZOJ1803][Spoj1487]Query on a tree III(dfs序+主席树)
- BZOJ1803: Spoj1487 Query on a tree III
- [BZOJ1803] Spoj1487 Query on a tree III
- bzoj1803: Spoj1487 Query on a tree III
- bzoj1803: Spoj1487 Query on a tree III
- 1803: Spoj1487 Query on a tree III
- SPOJ 1487 Query on a tree III 主席树,可持续化线段树
- SPOJ PTO7J Query on a tree III(dfs序+主席树)
- SPOJ PT07J Query on a tree III(dfs序,主席树)
- SPOJ 线段树(区间kth number) 1487. Query on a tree III
- 【主席树】 SPOJ Count on a tree
- spoj Count on a tree【主席树】
- bzoj2588 count on a tree 主席树
- 发个博客为什么要这么难?发个博客为什么要这么难?发个博客为什么要这么难?
- C Tips: 排序算法:快速排序(Quick sorting)
- Moto G 的开发者模式
- android更新链接不上服务器的解决方法
- document.getElementById的理解
- SPOJ1487. Query on a tree III 树链剖分+主席树
- 2014年3月31日--4月6日(共8小时,剩4500小时)
- 2014年4月7日---4月13日(共15小时,剩4485小时)
- jQuery学习第三课(选择器第三讲)
- setWebClient与setWebChromeClient之间的区别
- 不悔的青春
- libssh2静态库编译
- HTTP Error 404.2 - Not Found "The page you are requesting cannot be served because of the ISAPI and
- LeetCode (Single number 2)