codeforces 893F Subtree Minimum Query 线段树合并

来源:互联网 发布:淘宝达人文章怎么赚钱 编辑:程序博客网 时间:2024/06/05 18:50

简略题意:树上每个点存在一个点权,边权为1,每次询问点x的子树中,距离x小于等于k的所有点中最小值是多少。

强制在线,老老实实考虑数据结构解法…

对每个节点维护一棵线段树即可,父亲节点的线段树由自己本身和所有儿子节点合并而成。对每个点用其深度表示其在线段树对应的位置。

用到的只有单点更新,区间查询,合并。
qls:“线段树合并对如闪电!”

#define poj#ifdef poj#include <iostream>#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <vector>#include <string>#endif // poj#ifdef others#include <bits/stdc++.h>#endif // others//#define file#define all(x) x.begin(), x.end()using namespace std;const double eps = 1e-8;int dcmp(double x) { if(fabs(x)<=eps) return 0; return (x>0)?1:-1;};typedef long long LL;namespace solver {    const int maxn = 110000;    int n, r;    int a[maxn], dep[maxn];    vector<int> G[maxn];    int minv[maxn*40], rt[maxn*40], ls[maxn*40], rs[maxn*40], id = 1;    void pushup(int rt) {        minv[rt] = min(minv[ls[rt]], minv[rs[rt]]);    }    void upd(int p, int v, int l, int r, int &rt) {        if(rt == 0) rt = id++;        if(l == r) {            minv[rt] = v;            return ;        }        int m = l + r >> 1;        if(p <= m) upd(p, v, l, m, ls[rt]);        else upd(p, v, m+1, r, rs[rt]);        pushup(rt);    }    int merge(int &u, int v) {        if(!v) return u;        if(!u) return v;        int nownode = id++;        ls[nownode] = merge(ls[u], ls[v]);        rs[nownode] = merge(rs[u], rs[v]);        minv[nownode] = min(minv[u], minv[v]);        return nownode;    }    int ask(int L, int R, int l, int r, int rt) {        if(L <= l && R >= r) return minv[rt];        int ans = 0x3f3f3f3f;        int m = l + r >> 1;        if(L <= m) ans = min(ans, ask(L, R, l, m, ls[rt]));        if(R > m) ans = min(ans, ask(L, R, m+1, r, rs[rt]));        pushup(rt);        return ans;    }    void dfs(int u, int fa) {        upd(dep[u], a[u], 1, maxn-1, rt[u]);        for(auto v:G[u]) {            if(v == fa) continue;            dep[v] = dep[u] + 1;            dfs(v, u);            rt[u] = merge(rt[u], rt[v]);        }    }    void solve() {        memset(minv, 0x3f3f3f3f, sizeof minv);        scanf("%d%d", &n ,&r);        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);        int m;        for(int i = 1; i < n; i++) {            int u, v; scanf("%d%d", &u, &v);            G[u].push_back(v); G[v].push_back(u);        }        dep[r] = 1;        dfs(r, -1);        scanf("%d", &m);        int last_ans = 0;        for(int i = 1; i <= m; i++) {            int x, k;            scanf("%d%d", &x, &k);            x = (x + last_ans) % n + 1;            k = (k + last_ans) % n;            printf("%d\n", last_ans = ask(dep[x], min(dep[x] + k, maxn-1), 1, maxn-1, rt[x]));        }    }}int main() {    #ifdef file    freopen("gangsters.in", "r", stdin);    freopen("gangsters.out", "w", stdout);    #endif // file    solver::solve();    return 0;}
原创粉丝点击