zoukankan      html  css  js  c++  java
  • CF893F Subtree Minimum Query(主席树)

    CF893F Subtree Minimum Query(主席树)

    题目大意

    给你一颗有根树,点有权值,(m) 次询问,每次问你某个点的子树中距离其不超过 (k) 的点的权值的最小值。(边权均为 (1),点权有可能重复,(k) 值每次询问有可能不同)

    本题强制在线,真实询问计算方法:

    (x =(x'+ ext{lans})mod n + 1)
    (k=(k'+ ext{lans})mod n)

    其中 ( ext{lans}) 为上一次询问的答案,定义初始 ( ext{lans} = 0)

    数据范围

    对于 (100\%) 的数据:(1le n le 10^5)(1 le a_i le 10^9)(1 le m le 10^6)

    解题思路

    这题比较套路,在 x 的子树中可以化为 dfn 在 (dfn[x] o dfn[x]+siz[x]-1) 中,深度限制直接在加上一维即可,那么其实已经转化为简单的二维偏序问题了,直接用主席树求解即可

    #include <queue>
    #include <vector>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define MP make_pair
    #define ll long long
    #define fi first
    #define se second
    using namespace std;
    
    template <typename T>
    void read(T &x) {
        x = 0; bool f = 0;
        char c = getchar();
        for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
        for (;isdigit(c);c=getchar()) x=x*10+(c^48);
        if (f) x=-x;
    }
    
    template<typename F>
    inline void write(F x)
    {
    	static short st[30];short tp=0;
    	if(x<0) putchar('-'),x=-x;
    	do st[++tp]=x%10,x/=10; while(x);
    	while(tp) putchar('0'|st[tp--]);
    	putchar('
    ');
    }
    
    template <typename T>
    inline void Mx(T &x, T y) { x < y && (x = y); }
    
    template <typename T>
    inline void Mn(T &x, T y) { x > y && (x = y); }
    
    const int N = 100500;
    int h[N], ne[N<<1], to[N<<1], tot;
    inline void add(int x, int y) {
    	ne[++tot] = h[x], to[h[x] = tot] = y;
    }
    
    int ls[N<<5], rs[N<<5], mn[N<<5], T[N], L[N], R[N], num, cnt, n, m;
    
    const int inf = 1e9;
    int update(int pre, int l, int r, int x, int v) {
    	int rt = ++cnt; 
    	ls[rt] = ls[pre], rs[rt] = rs[pre];
    	mn[rt] = min(mn[pre], v);
    	if (l == r) return rt;
    	int mid = (l + r) >> 1;
    	if (x <= mid) ls[rt] = update(ls[pre], l, mid, x, v);
    	else rs[rt] = update(rs[pre], mid + 1, r, x, v);
    	return rt;
    }
    
    int query(int p, int l, int r, int L, int R) {
    	if (L <= l && r <= R) return mn[p];
    	int mid = (l + r) >> 1, tp = inf;
    	if (L <= mid) Mn(tp, query(ls[p], l, mid, L, R));
    	if (mid < R) Mn(tp, query(rs[p], mid + 1, r, L, R));
    	return tp;
    }
    
    vector<int> v[N];
    int val[N], dep[N], las, r;
    void dfs(int x, int fa) {
    	dep[x] = dep[fa] + 1, L[x] = ++num;
    	v[dep[x]].push_back(x);
    	for (int i = h[x]; i; i = ne[i]) 
    		if (to[i] != fa) dfs(to[i], x);
    	R[x] = num;
    }
    
    int main() {
    	read(n), read(r); mn[0] = inf;
    	for (int i = 1;i <= n; i++) read(val[i]);
    	for (int i = 1, x, y;i < n; i++)
    		read(x), read(y), add(x, y), add(y, x);
    	dfs(r, 0);
    	for (int i = 1;i <= n; i++, T[i] = T[i-1]) 
    		for (auto g: v[i]) T[i] = update(T[i], 1, n, L[g], val[g]);
    	read(m);
    	while (m--) {
    		int x, y; read(x), read(y);
    		x = (x + las) % n + 1, y = (y + las) % n;
    		write(las = query(T[min(dep[x] + y, n)], 1, n, L[x], R[x]));
    	}
    	return 0;
    }
    
  • 相关阅读:
    软件设计师 -算法设计与分析
    windows下git使用
    SourceTree免注册并连码云
    软件设计师-软件工程基础知识
    基本约瑟夫环问题详解
    SGU180(树状数组,逆序对,离散)
    POJ(1195)(单点修改,区间查询)(二维)
    C++ bitset
    冯志远0920
    怎样学好哲学(lucas+费马小定理)
  • 原文地址:https://www.cnblogs.com/Hs-black/p/13040410.html
Copyright © 2011-2022 走看看