• bzoj4448 [Scoi2015]情报传递 主席树+树上差分


    题目传送门

    https://lydsy.com/JudgeOnline/problem.php?id=4448

    题解

    练习一下主席树的基础练习题找回感觉。

    对于每一次询问,第一问显然随便做。

    第二问的话,可以发现就是要求出路径上的加入时间小于 (i - c - 1) 的点。

    这个东西似乎可以树上动态主席树?

    其实我们可以发现,后面加入的点对前面的查询没有影响,所以我们可以先一起吧整棵树上的点的加入时间都查出来,然后询问加入时间小于 (i-c+1) 的点。

    查询的时候可以用树上差分,就是加上 (x, y) 的树上前缀和,减去 (lca)(fa[lca])


    时间复杂度 (qlog n)

    #include<bits/stdc++.h>
    
    #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
    #define dbg(...) fprintf(stderr, __VA_ARGS__)
    #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define fi first
    #define se second
    #define pb push_back
    
    template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
    template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
    
    typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
    
    template<typename I> inline void read(I &x) {
    	int f = 0, c;
    	while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    	x = c & 15;
    	while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    	f ? x = -x : 0;
    }
    
    const int N = 2e5 + 7;
    
    int n, m, rr, dfc, nod;
    int f[N], tt[N], rt[N];
    int dep[N], siz[N], son[N], top[N], dfn[N], pre[N];
    
    struct Query { int x, y, c; } q[N];
    
    struct Edge { int to, ne; } g[N << 1]; int head[N], tot;
    inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
    inline void adde(int x, int y) { addedge(x, y), addedge(y, x); }
    
    struct Node { int lc, rc, val; } t[N * 20];
    inline void ins(int &o, int p, int L, int R, int x) {
    	t[o = ++nod] = t[p], ++t[o].val;
    	if (L == R) return;
    	int M = (L + R) >> 1;
    	if (x <= M) ins(t[o].lc, t[p].lc, L, M, x);
    	else ins(t[o].rc, t[p].rc, M + 1, R, x);
    }
    inline int qsum(int o1, int o2, int o3, int o4, int L, int R, int l, int r) {
    	if (l > r) return 0;
    	if (l <= L && R <= r) return t[o1].val + t[o2].val - t[o3].val - t[o4].val;
    	int M = (L + R) >> 1;
    	if (r <= M) return qsum(t[o1].lc, t[o2].lc, t[o3].lc, t[o4].lc, L, M, l, r);
    	if (l > M) return qsum(t[o1].rc, t[o2].rc, t[o3].rc, t[o4].rc, M + 1, R, l, r);
    	return qsum(t[o1].lc, t[o2].lc, t[o3].lc, t[o4].lc, L, M, l, r) + qsum(t[o1].rc, t[o2].rc, t[o3].rc, t[o4].rc, M + 1, R, l, r);
    }
    
    inline void dfs1(int x, int fa = 0) {
    	if (tt[x]) ins(rt[x], rt[fa], 1, m, tt[x]);
    	else rt[x] = rt[fa];
    	dep[x] = dep[fa] + 1, f[x] = fa, siz[x] = 1;
    	for fec(i, x, y) if (y != fa) dfs1(y, x), siz[x] += siz[y], siz[y] > siz[son[x]] && (son[x] = y);
    }
    inline void dfs2(int x, int pa) {
    	top[x] = pa, dfn[x] = ++dfc, pre[dfc] = x;
    	if (!son[x]) return; dfs2(son[x], pa);
    	for fec(i, x, y) if (y != f[x] && y != son[x]) dfs2(y, y);
    }
    inline int lca(int x, int y) {
    	while (top[x] != top[y]) dep[top[x]] > dep[top[y]] ? x = f[top[x]] : y = f[top[y]];
    	return dep[x] < dep[y] ? x : y;
    }
    
    inline void work() {
    	dfs1(rr), dfs2(rr, rr);
    	for (int i = 1; i <= m; ++i) if (q[i].x) {
    		int x = q[i].x, y = q[i].y, c = q[i].c, p = lca(x, y);
    		printf("%d %d
    ", dep[x] + dep[y] - (dep[p] << 1) + 1, qsum(rt[x], rt[y], rt[p], rt[f[p]], 1, m, 1, i - c - 1));
    	}
    }
    
    inline void init() {
    	read(n);
    	for (int i = 1; i <= n; ++i) read(f[i]), f[i] == 0 && (rr = i), f[i] && (addedge(f[i], i), 0);
    	read(m);
    	for (int i = 1; i <= m; ++i) {
    		int opt, x;
    		read(opt);
    		if (opt == 2) read(x), tt[x] = i;
    		else read(q[i].x), read(q[i].y), read(q[i].c);
    	}
    }
    
    int main() {
    #ifdef hzhkk
    	freopen("hkk.in", "r", stdin);
    #endif
    	init();
    	work();
    	fclose(stdin), fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    CodeForces 156B Suspects(枚举)
    CodeForces 156A Message(暴力)
    CodeForces 157B Trace
    CodeForces 157A Game Outcome
    HDU 3578 Greedy Tino(双塔DP)
    POJ 2609 Ferry Loading(双塔DP)
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛十六进制转换成十进制
  • 原文地址:https://www.cnblogs.com/hankeke/p/bzoj4448.html
Copyright © 2020-2023  润新知