[BZOJ 4196][Noi2015]软件包管理器
2016-02-27 20:56
453 查看
树链剖分
注意最好不要用0作为节点, 重儿子会挂
还有尽可能的开大数组
相信树剖的效率
注意最好不要用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; }
相关文章推荐
- 修改Ubuntu的默认启动项
- C语言实现双向非循环链表的逆序打印
- 安装clustalw-2.1
- Jquery对Cookie的操作
- delphi的TThread.CreateAnonymousThread导致界面卡死
- Leetcode ☞ 242. Valid Anagram ☆
- Codeforces 633 C Spy Syndrome 2 字典树
- [android] 测试的相关概念
- Xamarin Dropdown menu
- CSS3 入门2
- python实现高精度减法
- java创建对象的4中方法
- 【jsoncpp】json_value.cpp : fatal error C1083: 无法打开编译器生成的文件:No such file or directory
- 机房重构模板方法
- JQuery Uploadify 基于JSP的无刷新上传实例
- 软件工程文档总结
- Android ContentProvider源码分析
- python实现高精度加法
- 滚轮向下滚,自动加载内容
- Visual Studio 2012 编译错误【error C4996: 'scanf': This function or variable may be unsafe. 】的解决方案