[BZOJ4196][NOI2005]软件包管理器(链剖+dfs序)
来源:互联网 发布:js 算法 编辑:程序博客网 时间:2024/06/07 13:45
题目:
我是超链接
题解:
dfs序的in和out可以完美的把子树囊括在内,所以在维护的线段树上也是一段连续的区间,可以整体操作
首先关于安装问题,可以用状态0/1来表示
对于根到结点X的查询,非常容易
好了出于对树链剖分更深层次的理解,写一遍数组的意义:
in编号为i的点在线段树数组中的编号,sum编号为i的点在线段树中的存在的孩子个数【in是连接现实和虚拟的门。
添加软件包的时候,由于不是x的子树全部都要添加,必须呈链状修改
但删除就简单多了,呈团状子树全都没啦
代码:
#include <cstdio>#include <cstring>#include <iostream>#define N 100000#define MIN -19e+7using namespace std;int size[N*4],ww[N*4],son[N*4],fa[N*4],deep[N*2+5],delta[N*4+5];int top[N*4],in[N*4],out[N*4],totw=0;int sum[N*4],maxn[N*4],minn[N*4];int next[N*2+5],point[N*2+5],v[N*2+5],tot=0,cnt=0,n;void addline(int x,int y){ ++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; ++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x;}void updata(int now){sum[now]=sum[now<<1]+sum[now<<1|1];}void dfs_1(int now,int dep,int faa){ deep[now]=dep; fa[now]=faa; size[now]=1; int maxx=MIN; for (int i=point[now];i;i=next[i]) if (v[i]!=faa) { dfs_1(v[i],dep+1,now); size[now]+=size[v[i]]; if (size[v[i]]>maxx) { maxx=size[v[i]]; son[now]=v[i]; } }}void dfs_2(int now,int faa){ if (son[faa]!=now) top[now]=now; else top[now]=top[faa]; in[now]=++cnt; if (son[now]) { dfs_2(son[now],now); for (int i=point[now];i;i=next[i]) if (v[i]!=son[now] && v[i]!=faa) dfs_2(v[i],now); } out[now]=cnt;}void pushdown(int now,int l,int r,int mid){ if (delta[now]>=0) { delta[now<<1]=delta[now]; delta[now<<1|1]=delta[now]; sum[now<<1]=delta[now]*(mid-l+1); sum[now<<1|1]=delta[now]*(r-mid); delta[now]=-1; }}int qurry(int now,int l,int r,int lrange,int rrange){ if (lrange<=l && rrange>=r) return sum[now]; int mid=(l+r)>>1,ans=0; pushdown(now,l,r,mid); if (mid>=lrange) ans+=qurry(now<<1,l,mid,lrange,rrange); if (mid<rrange) ans+=qurry(now<<1|1,mid+1,r,lrange,rrange); return ans;} void change(int now,int l,int r,int lrange,int rrange,int v){ if (l>=lrange && rrange>=r) { delta[now]=v; sum[now]=v*(r-l+1); return; } int mid=(l+r)>>1; pushdown(now,l,r,mid); if (mid>=lrange)change(now<<1,l,mid,lrange,rrange,v); if (mid<rrange) change(now<<1|1,mid+1,r,lrange,rrange,v); updata(now);}int work(int u,int v,int id){ int f1=top[u],f2=top[v],summ=0; while (f1!=f2) { if (deep[f1]<deep[f2]) { swap(f1,f2); swap(u,v); } if (id==1) summ+=qurry(1,1,n,in[f1],in[u]); else change(1,1,n,in[f1],in[u],1); u=fa[f1]; f1=top[u]; } if (in[u]<in[v]) swap(u,v); if (id==1) summ+=qurry(1,1,n,in[v],in[u]); else change(1,1,n,in[v],in[u],1); return summ;}int main(){ int i,x,q; scanf("%d",&n); for (i=1;i<=n-1;i++) { scanf("%d",&x); addline(i+1,x+1); } dfs_1(1,1,0); dfs_2(1,0); memset(delta,128,sizeof(delta)); scanf("%d",&q); for (i=1;i<=q;i++) { char st[20];int ans=0; scanf("%s%d",st,&x); x++; if (st[0]=='i') { ans=work(1,x,1); printf("%d\n",deep[x]-ans); ans=work(1,x,2); } else { ans=qurry(1,1,n,in[x],out[x]); printf("%d\n",ans); change(1,1,n,in[x],out[x],0); } } }
0 0
- [BZOJ4196][NOI2005]软件包管理器(链剖+dfs序)
- [BZOJ4196][NOI2005]软件包管理器(链剖+dfs序)
- bzoj4196: [Noi2015]软件包管理器
- 【NOI2015】【BZOJ4196】软件包管理器
- [BZOJ4196][Noi2015]软件包管理器
- bzoj4196[Noi2015]软件包管理器
- bzoj4196【NOI2015】软件包管理器
- bzoj4196软件包管理器 noi2015
- [BZOJ4196] [Noi2015]软件包管理器
- 【NOI2015】BZOJ4196软件包管理器
- bzoj4196[NOI2015]软件包管理器
- bzoj4196: [NOI2015]软件包管理器
- bzoj4196: [Noi2015]软件包管理器
- bzoj4196: [Noi2015]软件包管理器
- bzoj4196: [Noi2015]软件包管理器
- BZOJ4196: [Noi2015]软件包管理器
- 【bzoj4196】[NOI2015]软件包管理器
- 【Bzoj4196】软件包管理器
- 李白打酒,蓝桥杯2014年第3题
- maven的基本原理和使用
- 《ACM程序设计》书中题目总结
- 旋转数组的最小数字
- 美团点评2017秋招笔试真题A
- [BZOJ4196][NOI2005]软件包管理器(链剖+dfs序)
- inotify配置使用详解
- 设计模式(五)原型模式
- springboot使用(一)
- 最近在做关于机械臂的控制
- 用两个栈实现队列
- Java多线程
- leetcode 142. Linked List Cycle II
- Qt信号槽与观察者模式