【树链剖分】[BZOJ 4196]软件包管理器
2015-07-23 16:43
393 查看
实际上就是个树链剖分,每次询问自己需要的到根节点中有多少开/开了,然后根据需要输出然后线段树Update的时候改一下改成每次更新全部,直接覆盖就行,每次扫描出来的一段肯定是上面半段开下面半段不开(分成两段)或者全部都处于开或者关,因为在链上任意一个处于开启状态那么之前的必须也处于开始状态。就是这样。
[code]#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; }
相关文章推荐
- Shi-Tomasi算子的运用 ,用于检测角点
- 统计数组中元素出现的次数——Java小程序
- 论文笔记:Chaotic Invariants of Lagrangian Particle Trajectories for Anomaly Detection in Crowded Scenes
- jQuery基本方法随笔
- 双端队列
- Storm Capacity Metric
- JFinal的架构介绍,JFinal实现极速开发的原理是什么?又是如何实现的?
- Java中的Hashtable实现方法
- Android4.4 WifiP2pSettings 中调用流程
- OC笔记-学习self时候2个target然后修改名字出现linker command failed with exit code 1 (use -v to see invocation)
- TRACE()的用法总结
- 删除功能在哪里
- POJ 1008 Maya Calendar(模拟)
- [转] Spring Security(01)——初体验
- 本内容中发现无效字符。处理资源 'file:///C:/Users/XDJ/Desktop/1111/press.xml' 时出错。第 5 行,位置: 11 <author>ƽ
- 手机安全卫士------主页面(HomeActivity)
- iOS for循环创建button,button的宽度根据上面的文字来自适应.
- Online Judge System For SzNOI 题库 语法百题 C++ d011
- Visual Studio 2015速递(1)——C#6.0新特性怎么用
- PO CREATE