您的位置:首页 > 其它

[BZOJ 4196][Noi2015]软件包管理器

2016-02-27 20:56 453 查看
树链剖分

注意最好不要用0作为节点, 重儿子会挂

还有尽可能的开大数组

相信树剖的效率

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

#define maxn 200010
using namespace std;

int n;

int h[maxn], cnt;
struct Edge{
	int to, next;
}edge[maxn];

void add(int u, int v){
	cnt ++;
	edge[cnt].to = v;
	edge[cnt].next = h[u];
	h[u] = cnt;
}

int size[maxn], pos[maxn], son[maxn], top[maxn], dfs_clock, dep[maxn];

int L[maxn], R[maxn], fa[maxn];

void dfs1(int u){
	size[u] = 1;
	dep[u] = dep[fa[u]] + 1;
	for(int i = h[u]; i; i = edge[i].next){
		int v = edge[i].to;
		fa[v] = u;
		dfs1(v);
		size[u] += size[v];
		if(size[v] > size[son[u]])
		    son[u] = v;
	}
}

void dfs2(int u, int tp){
	top[u] = tp;
	pos[u] = ++ dfs_clock;
	L[u] = dfs_clock;
	if(son[u])dfs2(son[u], tp);
	for(int i = h[u]; i; i = edge[i].next){
		int v = edge[i].to;
		if(v == son[u])continue;
		dfs2(v, v);
	}
	R[u] = dfs_clock;
}

struct Node{
	int l, r, lazy, sum;
}t[maxn << 2];

struct Segment{
	#define lc id << 1
	#define rc id << 1 | 1
	void build(int id, int l, int r){
		t[id].l = l, t[id].r = r;
		if(l == r)return;
		int mid = l + r >> 1;
		build(lc, l, mid);
		build(rc, mid + 1, r);
	}

	void pushdown(int id){
		if(t[id].lazy == 0)return;
		t[lc].lazy = t[rc].lazy = t[id].lazy;
		if(t[id].lazy < 0)t[id].sum = 0;
		else{
			if(id == 1)
				t[id].sum = n;
			else{
                int mid = t[id >> 1].l + t[id >> 1].r >> 1;
				if(t[id].r == mid)t[id].sum = mid - t[id].l + 1;
				else t[id].sum = t[id].r - mid;
			}
		}
		t[id].lazy = 0;
	}

	void Modify(int id, int l, int r, int val){
		pushdown(id);
		if(t[id].l == l && t[id].r == r){
			t[id].lazy = val;
			if(t[id].lazy > 0)t[id].sum = r - l + 1;
			else t[id].sum = 0;
			return;
  		}
		int mid = t[id].l + t[id].r >> 1;
		if(r <= mid){
			pushdown(rc);
			Modify(lc, l, r, val);
		}
		else if(l > mid){
			pushdown(lc);
			Modify(rc, l, r, val);
		}
		else{
			Modify(lc, l, mid, val);
			Modify(rc, mid + 1, r, val);
		}
		t[id].sum = t[lc].sum + t[rc].sum;
	}

	int ask(int id, int l, int r){
		pushdown(id);
		if(t[id].l == l && t[id].r == r)
			return t[id].sum;
        int mid = t[id].l + t[id].r >> 1;
		if(r <= mid)return ask(lc, l, r);
		else if(l > mid)return ask(rc, l, r);
		else return ask(lc, l, mid) + ask(rc, mid + 1, r);
	}
	#undef lc
	#undef rc
}T;

int Getans(int u, int val){
	int pd = T.ask(1, pos[u], pos[u]);
	if(val < 0 && pd == 0)
	    return 0;
	if(val > 0 && pd == 1)
	    return 0;
	int ans = 0;
	if(val > 0){
		ans = dep[u];
        while(~ u){
			ans -= T.ask(1, pos[top[u]], pos[u]);
			T.Modify(1, pos[top[u]], pos[u], 1);
			u = fa[top[u]];
		}
	}
	else{
		ans = T.ask(1, L[u], R[u]);
		T.Modify(1, L[u], R[u], -1);
	}
	return ans;
}

int main(){
	scanf("%d", &n);
	int u;
	for(int i = 2; i <= n; i ++){
		scanf("%d", &u);
		u ++;
		add(u, i);
	}
	dfs1(1);
	dfs2(1, 1);
	T.build(1, 1, n);
	fa[1] = -1;
	int test;
	char cmd[10];
	scanf("%d", &test);
	while(test --){
		scanf("%s%d", cmd, &u);
		u ++;
		printf("%d\n", Getans(u, cmd[0] == 'i' ? 1 : -1));
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: