zoukankan      html  css  js  c++  java
  • BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )

    Orz..跑得还挺快的#10

    自从会树链剖分后LCA就没写过倍增了...

    这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树

    -------------------------------------------------------------------------

    #include<bits/stdc++.h>
     
    #define rep(i, n) for(int i = 0; i < n; i++)
    #define clr(x, c) memset(x, c, sizeof(x))
    #define M(l, r) (((l) + (r)) >> 1)
    #define foreach(i, x) for(__typeof(x.begin()) i = x.begin(); i != x.end(); i++)
     
    using namespace std;
     
    const int maxn = 200009;
     
    int w[maxn], n, N, id[maxn];
    vector<int> G[maxn];
     
    namespace LCA {
        int top[maxn], son[maxn], dep[maxn], size[maxn], fa[maxn], TOP;
        
        void dfs(int x) {
       size[x] = 1; son[x] = -1;
       foreach(it, G[x]) if(*it != fa[x]) {
       dep[*it] = dep[x] + 1; 
       fa[*it] = x;
       dfs(*it);
       size[x] += size[*it];
       if(!~son[x] || size[*it] > size[son[x]])
           son[x] = *it;
       }
        }
        void DFS(int x) {
    top[x] = TOP;
    if(~son[x]) DFS(son[x]);
    foreach(it, G[x]) if(*it != son[x] && *it != fa[x])
        DFS(TOP = *it);
    }
       
    void init() {
    dep[0] = 0; fa[0] = -1;
    dfs(0); DFS(TOP = 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] ? x : y;
    }
    }
     
    struct Node {
    Node *l, *r;
    int s;
    } pool[maxn * 40], *pt = pool, *null, *root[maxn];
     
    void init() {
    null = pt++; null->s = 0;
    null->l = null->r = null;
    }
     
    int v;
    Node* modify(Node* t, int l, int r) {
    Node* h = pt++;
    h->s = t->s + 1;
    if(r > l) {
    int m = M(l, r);
    if(v <= m) {
    h->l = modify(t->l, l, m);
    h->r = t->r;
    } else {
    h->l = t->l;
    h->r = modify(t->r, m + 1, r);
    }
    }
    return h;
    }
     
    void build(int x, int fa = -1, Node* p = null) {
    v = w[x] + 1;
    root[x] = modify(p, 1, N);
    foreach(it, G[x]) if(*it != fa)
       build(*it, x, root[x]);
    }
     
    inline int read() {
    char c = getchar();
    int ans = 0, f = 1;
    for(; !isdigit(c); c = getchar())
       if(c == '-') f = -1;
    for(; isdigit(c); c = getchar()) 
       ans = ans * 10 + c - '0';
    return ans * f;
    }
     
    int ans = 0;
    void work(bool F) {
    int x = (read()^ans) - 1, y = read() - 1, k = read(), lca = LCA::LCA(x, y);
    Node *X = root[x], *Y = root[y], *A = root[lca], *P = lca ? root[LCA::fa[lca]] : null;
    int L = 1, R = N;
    while(L < R) {
    int s = X->l->s + Y->l->s - A->l->s - P->l->s, m = M(L, R);
    if(s >= k) {
    X = X->l; Y = Y->l; A = A->l; P = P->l;
    R = m;
    } else {
    X = X->r; Y = Y->r; A = A->r; P = P->r;
    k -= s;
    L = m + 1;
    }
    }
    ans = id[L - 1];
    printf("%d", ans);
    if(F) putchar(' ');
    }
     
    int main() {
    freopen("test.in", "r", stdin);
    init();
    n = read();
    int m = read();
    rep(i, n) {
    id[i] = w[i] = read();
       G[i].clear();
    }
    sort(id, id + n);
    N = unique(id, id + n) - id;
    rep(i, n) w[i] = lower_bound(id, id + N, w[i]) - id;
    rep(i, n - 1) {
    int u = read() - 1, v = read() - 1;
    G[u].push_back(v);
    G[v].push_back(u);
    }
    LCA::init();
    build(0);
    while(m--) work(m);
    return 0;
    }

    ------------------------------------------------------------------------- 

    2588: Spoj 10628. Count on a tree

    Time Limit: 12 Sec  Memory Limit: 128 MB
    Submit: 2675  Solved: 606
    [Submit][Status][Discuss]

    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 5
    105 2 9 3 8 5 7 7
    1 2
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5 1
    0 5 2
    10 5 3
    11 5 4
    110 8 2

    Sample Output

    2
    8
    9
    105
    7

    HINT




    HINT:

    N,M<=100000

    暴力自重。。。

    Source

  • 相关阅读:
    Socket经验记录
    有了WCF,Socket是否已人老珠黄?
    更新Svn客户端后,右键菜单中没有TortoiseSVN了
    线程已被中止 “Thread was being aborted”
    c# 温故而知新: 线程篇(一)
    SOCKET是多线程安全的吗? [问题点数:40分,结帖人CSDN]
    <base href=""/> 的应用
    Python Twisted 框架中 socket通信
    本人作品-〉VPS应用>Discuz网页斗地主插件
    浅析 c# Queue
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4687736.html
Copyright © 2011-2022 走看看