HYSBZ 2588Spoj 10628. Count on a tree

来源:互联网 发布:it行业 云计算 编辑:程序博客网 时间:2024/05/01 08:31

Description

给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

Input

第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。

Output

 
M行,表示每个询问的答案。

Sample Input

8 5105 2 9 3 8 5 7 71 21 31 43 53 63 74 82 5 10 5 210 5 311 5 4110 8 2

Sample Output

2891057 

Hint




HINT:

N,M<=100000

暴力自重。。。


正解,每个点维护一个可持久化线段树,通过容斥可以知道,链(x,y)等于tree(x)+tree(y)-tree(lca(x,y))-tree(fa[lca(x,y)])

然后就是线段树上求第k小了。注意最后一行不要回车,会格式错误。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define rep(i,j,k) for(int i=j;i<=k;i++)#define per(i,j,k) for(int i=j;i>=k;i--)#define loop(i,j,k) for (int i=j;i!=-1;i=k[i])#define inone(x) scanf("%d",&x)#define intwo(x,y) scanf("%d%d",&x,&y)#define lson x<<1,l,mid#define rson x<<1|1,mid+1,rconst int low(int x) { return x&-x; }const int N = 2e5 + 10;int n, m, nn, x, y, z;int ft[N], nt[N], u[N], v[N], a[N], sz;int ct[N], mx[N], fa[N];int dep[N], top[N];int rt[N], L[N * 20], R[N * 20], f[N * 20];void add(int x, int &y, int l, int r, int u){y = ++sz; L[y] = L[x]; R[y] = R[x]; f[y] = f[x] + 1;if (l == r) return;int mid = l + r >> 1;if (u <= mid) add(L[x], L[y], l, mid, u);else add(R[x], R[y], mid + 1, r, u);}void dfs(int x, int f){add(rt[f], rt[x], 1, nn, v[x]);ct[x] = 1; mx[x] = 0;fa[x] = f; dep[x] = dep[f] + 1;loop(i, ft[x], nt){if (u[i] == f) continue;dfs(u[i], x);ct[x] += ct[u[i]];if (ct[u[i]] > ct[mx[x]]) mx[x] = u[i];}}void Dfs(int x, int t){top[x] = !t ? x : top[fa[x]];if (mx[x]) Dfs(mx[x], 1);loop(i, ft[x], nt){if (u[i] == fa[x] || u[i] == mx[x]) continue;Dfs(u[i], 0);}}int lca(int x, int y){for (; top[x] != top[y]; x = fa[top[x]]){if (dep[top[x]] < dep[top[y]]) swap(x, y);}return dep[x] > dep[y] ? y : x;}int get(int x, int y, int z){int u = lca(x, y), v = fa[u];int g[4] = { rt[x],rt[u],rt[y],rt[v] };for (int l = 1, r = nn; l < r;){int mid = l + r >> 1, res = 0;for (int i = 0, j = 1; i < 4; i++, j *= -1){res += f[L[g[i]]] * j;}if (res >= z){rep(i, 0, 3) g[i] = L[g[i]];r = mid;}else{l = mid + 1;rep(i, 0, 3) g[i] = R[g[i]];z -= res;}if (l == r) return l;}}int main(){while (intwo(n, m) != EOF){rep(i, 1, n){inone(v[i]);a[i] = v[i], ft[i] = -1;}sort(a + 1, a + n + 1);nn = unique(a + 1, a + n + 1) - a - 1;rep(i, 1, n) v[i] = lower_bound(a + 1, a + nn + 1, v[i]) - a;rt[0] = L[0] = R[0] = f[0] = ct[0] = dep[0] = sz = 0;rep(i, 1, n - 1){intwo(x, y);u[sz] = y; nt[sz] = ft[x]; ft[x] = sz++;u[sz] = x; nt[sz] = ft[y]; ft[y] = sz++;}dfs(1, sz = 0); Dfs(1, 0);for (int s = 0; m--; ){intwo(x, y); inone(z);x ^= s;s = a[get(x, y, z)];printf("%d%s", s, m ? "\n" : "");}}return 0;}

用树链剖分+二分答案+线段树,效率nlog^4(n)果断超时了,纪念一下。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define rep(i,j,k) for(int i=j;i<=k;i++)#define per(i,j,k) for(int i=j;i>=k;i--)#define loop(i,j,k) for (int i=j;i!=-1;i=k[i])#define inone(x) scanf("%d",&x)#define intwo(x,y) scanf("%d%d",&x,&y)#define lson x<<1,l,mid#define rson x<<1|1,mid+1,rconst int low(int x) { return x&-x; }const int N = 2e5 + 10;int n, m, nn, x, y, z;int ft[N], nt[N], u[N], v[N], sz;int a[N], b[N];int ct[N], mx[N], fa[N], to[N], fr[N];int dep[N], top[N];int f[20][N];void dfs(int x, int f){ct[x] = 1; mx[x] = 0;fa[x] = f; dep[x] = dep[f] + 1;loop(i, ft[x], nt){if (u[i] == f) continue;dfs(u[i], x);ct[x] += ct[u[i]];if (ct[u[i]] > ct[mx[x]]) mx[x] = u[i];}}void Dfs(int x, int t){top[x] = !t ? x : top[fa[x]];to[x] = ++sz; fr[sz] = x;if (mx[x]) Dfs(mx[x], 1);loop(i, ft[x], nt){if (u[i] == fa[x] || u[i] == mx[x]) continue;Dfs(u[i], 0);}}void build(int x, int l, int r){if (l == r) { f[x][l] = v[fr[l]]; return; }int mid = l + r >> 1;build(x + 1, l, mid); build(x + 1, mid + 1, r);for (int i = l, j = l, k = mid + 1; i <= r; i++){if (k > r || j <= mid&&f[x + 1][j] <= f[x + 1][k]) f[x][i] = f[x + 1][j++];else f[x][i] = f[x + 1][k++];}}int get(int x, int l, int r, int ll, int rr, int v){if (ll <= l&&r <= rr) return upper_bound(f[x] + l, f[x] + r + 1, v) - f[x] - l;int mid = l + r >> 1, res = 0;if (ll <= mid) res += get(x + 1, l, mid, ll, rr, v);if (rr > mid) res += get(x + 1, mid + 1, r, ll, rr, v);return res;}int check(int x, int y, int z){int res = 0;for (; top[x] != top[y]; x = fa[top[x]]){if (dep[top[x]] < dep[top[y]]) swap(x, y);res += get(0, 1, n, to[top[x]], to[x], z);}if (dep[x] > dep[y]) swap(x, y);res += get(0, 1, n, to[x], to[y], z);return res;}int main(){while (intwo(n, m) != EOF){rep(i, 1, n){inone(v[i]);a[i] = v[i], ft[i] = -1;}sort(a + 1, a + n + 1);nn = unique(a + 1, a + n + 1) - a;rep(i, 1, n) v[i] = lower_bound(a + 1, a + nn, v[i]) - a;ct[0] = dep[0] = sz = 0;rep(i, 1, n - 1){intwo(x, y);u[sz] = y; nt[sz] = ft[x]; ft[x] = sz++;u[sz] = x; nt[sz] = ft[y]; ft[y] = sz++;}dfs(1, 0); Dfs(1, sz = 0); build(0, 1, n);int s = 0;while (m--){intwo(x, y); inone(z);x ^= s;int q = 1, h = nn, mid;while (q <= h){mid = q + h >> 1;if (check(x, y, mid) >= z) h = mid - 1;else q = mid + 1;}printf("%d%s", s = a[q], m ? "\n" : "");}}return 0;}


0 0
原创粉丝点击