• BZOJ2588 Spoj 10628. Count on a tree


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2588

    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行,表示每个询问的答案。

    建立一棵可持久化权值线段树,对于树上的每一个点,以它的父亲节点为上一个版本,根节点的父亲节点是0

    询问u与v节点之间第K小的点权,就是询问 (root,u) + (root,v) - (root,lca(u,v)) - (root,fa(lca(u,v))) 第K小的点权,在权值线段树上二分即可。

    debug记:建可持久化线段树要从根节点往下建而不是按照点的编号建。不要把建树写残。

    Orz教主的指针版主席树,跑得比香港记者还快……

    2016.3.2 17:34 update:这份代码在SPOJ上跑了#16……教主的居然WA了?

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #define rep(i,l,r) for(int i=l; i<=r; i++)
     6 #define clr(x,y) memset(x,y,sizeof(x))
     7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
     8 using namespace std;
     9 const int maxn = 100010;
    10 inline int read(){
    11     int ans = 0, f = 1;
    12     char c = getchar();
    13     for(; !isdigit(c); c = getchar())
    14     if (c == '-') f = -1;
    15     for(; isdigit(c); c = getchar())
    16     ans = ans * 10 + c - '0';
    17     return ans * f;
    18 }
    19 struct Edge{
    20     Edge* pre; int to,cost;
    21 }edge[maxn<<1],*last[maxn],*pt = edge;
    22 int n,m,k,x,y,N,cnt=0,lastans=0,w[maxn],id[maxn],dep[maxn],fa[maxn],size[maxn],top[maxn];
    23 int rt[maxn],ls[maxn*20],rs[maxn*20],sum[maxn*20];
    24 bool vis[maxn];
    25 inline void addedge(int x,int y){
    26     pt->pre = last[x]; pt->to = y; last[x] = pt++;
    27 }
    28 void dfs(int x){
    29     vis[x] = 1; size[x] = 1;
    30     travel(x){
    31         if (vis[p->to]) continue;
    32         dep[p->to] = dep[x] + 1;
    33         fa[p->to] = x;
    34         dfs(p->to); size[x] += size[p->to];
    35     }
    36 }
    37 void dfs(int x,int chain){
    38     int k = 0; top[x] = chain;
    39     travel(x) if (dep[p->to] > dep[x] && size[p->to] > size[k]) k = p->to;
    40     if (!k) return;
    41     dfs(k,chain);
    42     travel(x) if (p->to != k && dep[p->to] > dep[x])
    43     dfs(p->to,p->to);
    44 }
    45 inline int lca(int x,int y){
    46     while (top[x] != top[y]){
    47         if (dep[top[x]] < dep[top[y]]) swap(x,y);
    48         x = fa[top[x]];
    49     }
    50     return dep[x] < dep[y] ? x : y;
    51 }
    52 void insert(int l,int r,int x,int &y,int v){
    53     y = ++cnt; sum[y] = sum[x] + 1;
    54     if (l == r) return;
    55     ls[y] = ls[x]; rs[y] = rs[x];
    56     int mid = (l + r) >> 1;
    57     if (v <= mid) insert(l,mid,ls[x],ls[y],v);
    58     else insert(mid+1,r,rs[x],rs[y],v);
    59 }
    60 int query(int x,int y,int k){
    61     int a = x, b = y, c = lca(x,y), d = fa[c];
    62     a = rt[a], b = rt[b], c = rt[c], d = rt[d];
    63     int l = 1, r = N;
    64     while (l < r){
    65         int mid = (l + r) >> 1;
    66         int now = sum[ls[a]] + sum[ls[b]] - sum[ls[c]] - sum[ls[d]];
    67         if (now >= k) r = mid, a = ls[a], b = ls[b], c = ls[c], d = ls[d];
    68         else k -= now, l = mid + 1, a = rs[a], b = rs[b], c = rs[c], d = rs[d];
    69     }
    70     return id[l];
    71 }
    72 void build(int x){
    73     travel(x) if (p->to != fa[x]) insert(1,N,rt[x],rt[p->to],w[p->to]);
    74     travel(x) if (p->to != fa[x]) build(p->to);
    75 }
    76 int main(){
    77     n = read(); m = read(); clr(last,0);
    78     rep(i,1,n) w[i] = id[i] = read();
    79     rep(i,1,n-1){
    80         x = read(); y = read(); addedge(x,y); addedge(y,x);
    81     }
    82     sort(id+1,id+n+1);
    83     N = unique(id+1,id+n+1) - id - 1;
    84     rep(i,1,n) w[i] = lower_bound(id+1,id+N+1,w[i]) - id;
    85     clr(vis,0); dep[1] = 0; fa[1] = 0; dfs(1); dfs(1,1);
    86     insert(1,N,rt[0],rt[1],w[1]);
    87     build(1);
    88     rep(i,1,m){
    89         x = read(); y = read(); k = read();
    90         x ^= lastans;
    91         lastans = query(x,y,k);
    92         printf("%d",lastans);
    93         if (i != m) printf("
    ");
    94     }
    95     return 0;
    96 }
    View Code
  • 相关阅读:
    使用简单的反射技术重构组合查询串功能
    沤血分享之:使用Opera浏览器技巧全集
    项目中用到的RE分析
    关于调用新浪微博与腾讯微博
    正则 (?i,m,s,x,g)
    求职路 第二章 深圳篇
    12320平台架构及部署
    网站会员密码
    求职路 第二章 技术篇
    TFS故障一二
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj2588.html
Copyright © 2020-2023  润新知