zoukankan      html  css  js  c++  java
  • 洛谷P2146 [NOI2015]软件包管理器 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2146
    本题涉及算法:

    • 树链剖分;
    • 线段树(区间更新及求和,涉及懒惰标记)

    然后对于每次 install x ,需要将 x1 的路径上面的点全都置为1。
    那么在置为1之前统计一下节点数量 num1,
    在置为1之后统计一下节点数量 num2,
    答案就是 num2 - num1(当然,也可以通过节点深度 dep[x] 来获得节点数量)。

    对于每次 unistall x,需要将 x 为根的子树上面的点全都置为0。
    那么在置为0之前统计一下权值为1的节点数量 num1,
    在置为0之后统计一下权值为1的节点数量 num2,
    答案就是 num1-num2(当然,num2 其实就等于 0)。

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    #define INF (1<<29)
    const int maxn = 100010;
    int fa[maxn],
    	dep[maxn],
    	size[maxn],
    	son[maxn],
    	top[maxn],
    	seg[maxn], seg_cnt,
    	rev[maxn],
    	n,
    	sumv[maxn<<2], lazy[maxn<<2];
    vector<int> g[maxn];
    void dfs1(int u, int p) {
    	size[u] = 1;
    	for (vector<int>::iterator it = g[u].begin(); it != g[u].end(); it ++) {
    		int v = (*it);
    		if (v == p) continue;
    		fa[v] = u;
    		dep[v] = dep[u] + 1;
    		dfs1(v, u);
    		size[u] += size[v];
    		if (size[v] >size[son[u]]) son[u] = v;
    	}
    }
    void dfs2(int u, int tp) {
    	seg[u] = ++seg_cnt;
    	rev[seg_cnt] = u;
    	top[u] = tp;
    	if (son[u]) dfs2(son[u], tp);
    	for (vector<int>::iterator it = g[u].begin(); it != g[u].end(); it ++) {
    		int v = (*it);
    		if (v == fa[u] || v == son[u]) continue;
    		dfs2(v, v);
    	}
    }
    #define lson l, mid, rt<<1
    #define rson mid+1, r, rt<<1|1
    void push_down(int rt, int len) {
    	if (lazy[rt] != -1) {
    		int l_len=len-len/2, r_len = len/2;
    		lazy[rt<<1] = lazy[rt];
    		lazy[rt<<1|1] = lazy[rt];
    		sumv[rt<<1] = lazy[rt] * l_len;
    		sumv[rt<<1|1] = lazy[rt] * r_len;
    		lazy[rt] = -1;
    	}
    }
    void push_up(int rt) {
    	sumv[rt] = sumv[rt<<1] + sumv[rt<<1|1];
    }
    void build(int l, int r, int rt) {
    	lazy[rt] = -1;
    	int mid = (l + r) / 2;
    	if (l == r) {
    		sumv[rt] = 0;
    		return;
    	}
    	build(lson); build(rson);
    	push_up(rt);
    }
    void update(int L, int R, long long v, int l, int r, int rt) {
    	if (L <= l && r <= R) {
    		sumv[rt] = (r-l+1) * v;
    		lazy[rt] = v;
    		return;
    	}
    	push_down(rt, r-l+1);
    	int mid = (l + r) / 2;
    	if (L <= mid) update(L, R, v, lson);
    	if (R > mid) update(L, R, v, rson);
    	push_up(rt);
    }
    long long query_sum(int L, int R, int l, int r, int rt) {
    	if (L <= l && r <= R) return sumv[rt];
    	push_down(rt, r-l+1);
    	int mid = (l + r) / 2;
    	long long tmp = 0;
    	if (L <= mid) tmp += query_sum(L, R, lson);
    	if (R > mid) tmp += query_sum(L, R, rson);
    	return tmp;
    }
    int t_ask(int u) {
    	int res = 0;
    	while (top[u] != 1) {
    		res += query_sum(seg[top[u]], seg[u], 1, n, 1);
    		u = fa[top[u]];
    	}
    	res += query_sum(seg[1], seg[u], 1, n, 1);
    	return res;
    }
    void t_update(int u) {
    	while (top[u] != 1) {
    		update(seg[top[u]], seg[u], 1, 1, n, 1);
    		u = fa[top[u]];
    	}
    	update(seg[1], seg[u], 1, 1, n, 1);
    }
    int m, x;
    string op;
    int main() {
    	cin >> n;
    	for (int i = 2; i <= n; i ++) {
    		cin >> x;
    		g[x+1].push_back(i);
    	}
    	dep[1] = fa[1] = 1;
    	dfs1(1, -1);
    	dfs2(1, 1);
    	build(1, n, 1);
    	cin >> m;
    	while (m --) {
    		cin >> op >> x;
    		x ++;
    		if (op == "install") {
    			int num1 = t_ask(x);
    			t_update(x);
    			int num2 = t_ask(x);
    			cout << num2 - num1 << endl;
    		}
    		else {	// uninstall
    			int num1 = query_sum(seg[x], seg[x]+size[x]-1, 1, n, 1);
    			update(seg[x], seg[x]+size[x]-1, 0, 1, n, 1);
    			int num2 = query_sum(seg[x], seg[x]+size[x]-1, 1, n, 1);
    			cout << num1 - num2 << endl;
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Binary Search Tree Iterator 解答
    Invert Binary Tree 解答
    Min Stack 解答
    Trapping Raining Water 解答
    Candy 解答
    Jump Game II 解答
    Implement Hash Map Using Primitive Types
    Gas Station 解答
    Bucket Sort
    HashMap 专题
  • 原文地址:https://www.cnblogs.com/quanjun/p/12005248.html
Copyright © 2011-2022 走看看