4448: [Scoi2015]情报传递 dfs序+主席树
2016-03-22 07:44
423 查看
按照dfs序建主席树,把每个点出现的时刻作为权值加入,每次寻找<=i−c−1的值的个数。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MN 10000005 #define N 200005 using namespace std; int n,Q,cnt,tot,dfn,size,Root; int ls[MN],rs[MN],sum[MN]; int deep ,head ,list ,next ,id ,pos ,root ,v ,fa [19]; struct node { int x,y,c; }; node query ; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline void insert(int x,int y) { next[++cnt]=head[x]; head[x]=cnt; list[cnt]=y; } void dfs(int x) { id[x]=++dfn; pos[dfn]=x; for (int i=1;(1<<i)<=deep[x];i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for (int i=head[x];i;i=next[i]) { fa[list[i]][0]=x; deep[list[i]]=deep[x]+1; dfs(list[i]); } } inline int lca(int x,int y) { if (deep[x]<deep[y]) swap(x,y); int t=deep[x]-deep[y]; for (int i=0;(1<<i)<=t;i++) if ((1<<i)&t) x=fa[x][i]; for (int i=18;~i;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return x==y?x:fa[x][0]; } void update(int l,int r,int x,int &y,int val) { y=++size; sum[y]=sum[x]+(val!=0); if (l==r) return; ls[y]=ls[x]; rs[y]=rs[x]; int mid=l+r>>1; if (val<=mid) update(l,mid,ls[x],ls[y],val); else update(mid+1,r,rs[x],rs[y],val); } inline int ask(int x,int y,int z,int MAX) { int a=x,b=y,c=z,d=fa[c][0]; a=root[id[a]]; b=root[id[b]]; c=root[id[c]]; d=root[id[d]]; int l=1,r=Q,ans=0; while (l!=r) { int mid=l+r>>1; if (MAX<mid) { r=mid; a=ls[a]; b=ls[b]; c=ls[c]; d=ls[d]; } else { l=mid+1; ans+=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]]; a=rs[a]; b=rs[b]; c=rs[c]; d=rs[d]; } } return ans; } int main() { n=read(); for (int i=1;i<=n;i++) { int p=read(); if (!p) Root=i; else insert(p,i); } dfs(Root); Q=read(); for (int i=1;i<=Q;i++) { int opt=read(); if (opt==1) query[++tot].x=read(),query[tot].y=read(),query[tot].c=i-read()-1; else { int t=read(); if (!v[t]) v[t]=i; } } for (int i=1;i<=n;i++) update(1,Q,root[id[fa[pos[i]][0]]],root[i],v[pos[i]]); for (int i=1;i<=tot;i++) { int t=lca(query[i].x,query[i].y); printf("%d ",deep[query[i].x]+deep[query[i].y]-2*deep[t]+1); if (query[i].c<1) puts("0"); else printf("%d\n",ask(query[i].x,query[i].y,t,query[i].c)); } return 0; }
相关文章推荐
- 自定义类的归解档
- Android 微信支付总结
- 配置MySQL的Path变量
- linux命令
- 快速排序【模板】
- C++ 对象模型(二)
- [BZOJ 3439]Kpm的MC密码
- c++四种分配内存的方法整理
- 网络流建模总结
- Openlayers2中统计图的实现
- Openlayers2中统计图的实现
- C++中overload,override,overwrite的区别
- Python 提示 no module named win32api
- 23.数据类型和sizeof运算符
- nrf24l01+arduino
- 动态绑定和静态绑定,以及 缺省参数的静态绑定解释
- postgresql获取json结果
- .Net使用RabbitMQ详解
- 使用Nancy打造TaskManager2.0管理系统
- 送给微软中文.NET社区的一份礼物,.NET FM