【树链剖分】[BZOJ 4196]软件包管理器
来源:互联网 发布:上海优化公司hxwlkj 编辑:程序博客网 时间:2024/05/16 18:01
实际上就是个树链剖分,每次询问自己需要的到根节点中有多少开/开了,然后根据需要输出然后线段树Update的时候改一下改成每次更新全部,直接覆盖就行,每次扫描出来的一段肯定是上面半段开下面半段不开(分成两段)或者全部都处于开或者关,因为在链上任意一个处于开启状态那么之前的必须也处于开始状态。就是这样。
#include <cstdio>#include <algorithm>#include <cstring>//#include <conio.h>#include <iostream>using namespace std;const int MAXN = 100000;typedef long long LL;LL add[MAXN<<2], sum[MAXN<<2];int heavyson[MAXN+10], sons[MAXN+10], id[MAXN+10], last[MAXN+10], top[MAXN+10], idcnt;int depend[MAXN+10], fid[MAXN+10], n;struct node{ int v; node *next;}Edges[MAXN*2+10], *ecnt=Edges, *adj[MAXN+10];void addedge(int u, int v){ ++ecnt; ecnt->v = v; ecnt->next = adj[u]; adj[u] = ecnt;}void PushUp(int rt){sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void PushDown(int rt,int m){ if (add[rt] != 0) { add[rt<<1] = add[rt<<1|1] = add[rt]; if(add[rt] == -1) add[rt] = 0; sum[rt<<1] = add[rt] * (m - (m >> 1)); sum[rt<<1|1] = add[rt] * (m >> 1); add[rt] = 0; }}void update(int L,int R,int c,int l,int r,int rt) { if (L <= l && r <= R) { add[rt] = c; sum[rt] = (c==-1?0:1) * (r - l + 1); return ; } PushDown(rt , r - l + 1); int mid = (l + r) >> 1; if (L <= mid) update(L , R , c , l, mid, rt << 1); if (mid < R) update(L , R , c , mid+1, r, (rt<<1)|1); PushUp(rt);}LL query(int L,int R,int l,int r,int rt) { if (L <= l && r <= R){ return sum[rt]; } PushDown(rt , r - l + 1); int mid = (l + r) >> 1; LL ret = 0; if (L <= mid) ret += query(L , R , l, mid, rt<<1); if (mid < R) ret += query(L , R , mid+1, r, (rt<<1)|1); return ret;}void dfs(int u){ sons[u] = 1; heavyson[u] = -1; for(node *p=adj[u];p;p=p->next){ dfs(p->v); sons[u] += sons[p->v]; if(heavyson[u] == -1 || sons[p->v] > sons[heavyson[u]]) heavyson[u] = p->v; }}void dfs2(int u, int tp){ id[u] = ++idcnt; fid[idcnt] = u; if(tp == -1) tp = top[u] = idcnt; else top[u] = tp; if(heavyson[u] > 0) dfs2(heavyson[u], tp); for(node *p=adj[u];p;p=p->next) if(p->v != heavyson[u]){ dfs2(p->v, -1); } last[u] = idcnt;}int query_on(int u){ int tp = top[u], ret = 0, counter=0; while(true){ counter += id[u]-tp+1; if(tp == 1){ ret += query(1, id[u], 1, idcnt, 1); update(top[u], id[u], 1, 1, idcnt, 1); return counter - ret; } ret += query(top[u], id[u], 1, idcnt, 1); update(top[u], id[u], 1, 1, idcnt, 1); u = depend[fid[tp]]; tp = top[u]; } return -1;}int query_off(int u){ int ret = query(id[u], last[u], 1, idcnt, 1); update(id[u], last[u], -1, 1, idcnt, 1); return ret;}char s[70];int main() { //printf("%.3lf\n", (1.0 * sizeof(heavyson) + sizeof(sons) + sizeof(id) + sizeof(fid) + sizeof (top) + sizeof(Edges) + sizeof(depend) + sizeof(add) + sizeof(sum) )/1024.0/1024.0); //getch(); scanf("%d", &n); for(int i=1;i<n;i++){ scanf("%d", &depend[i]); addedge(depend[i], i); } dfs(0); dfs2(0,-1); int q, i_s; scanf("%d", &q); for(int i=0;i<q;i++){ scanf("%s%d", s, &i_s); if(s[0] == 'u') printf("%d\n", query_off(i_s)); else printf("%d\n", query_on(i_s)); } return 0;}
0 0
- 【树链剖分】[BZOJ 4196]软件包管理器
- BZOJ-4196 软件包管理器 树链剖分
- 【树链剖分】【NOI 2015】【bzoj 4196】软件包管理器
- 【树链剖分】[BZOJ 4196][NOI 2014]软件包管理器
- BZOJ 4196 软件包管理器(树链剖分子树)
- BZOJ 4196([Noi2015]软件包管理器-树链剖分)
- BZOJ 4196: [Noi2015]软件包管理器 树链剖分
- [BZOJ 4196][Noi2015]软件包管理器
- bzoj 4196: [Noi2015]软件包管理器
- BZOJ 4196 [Noi2015]软件包管理器
- bzoj 4196: [Noi2015]软件包管理器
- BZOJ 4196 [Noi2015]软件包管理器
- |BZOJ 4196|树链剖分|线段树|[Noi2015]软件包管理器
- bzoj-4196 NOI-2015 软件包管理器
- BZOJ[4196][Noi2015]洛谷[2146]软件包管理器
- 4196: [Noi2015]软件包管理器
- HYSBZ 4196 软件包管理器
- 4196: [Noi2015]软件包管理器
- 远程通信的几种选择(RPC,Webservice,RMI,JMS的区别)
- 根据数据的父子关系创建树形结构并实现遍历
- SMS 短信发送程序
- 论文笔记:Chaotic Invariants of Lagrangian Particle Trajectories for Anomaly Detection in Crowded Scenes
- 获得一个数组中所有元素进行的全排列,获得其中最小的数字
- 【树链剖分】[BZOJ 4196]软件包管理器
- Java内存泄露的理解与解决
- openCV使用心得
- log4j生成有日期的日志文件名
- [Android5 系列二] 1. 全实例之控件(Widget)
- 与人为善,于己为善
- 面向对象设计六大基本原则
- 虚拟机Ubuntu14.04+Caffe+libsvm对数据集进行分类
- git 冲突