题目:
奈特公司是一个巨大的情报公司,它有着庞大的情报网络。情报网络中共有n名情报员。每名情报员口J-能有
若T名(可能没有)下线,除1名大头日外其余n-1名情报员有且仅有1名上线。奈特公司纪律森严,每
名情报员只能与自己的上、下线联系,同时,情报网络中仟意两名情报员一定能够通过情报网络传递情报。
奈特公司每天会派发以下两种任务中的一个任务:
1.搜集情报:指派T号情报员搜集情报
2.传递情报:将一条情报从X号情报员传递给Y号情报员
情报员最初处于潜伏阶段,他们是相对安全的,我们认为此时所有情报员的危险值为0;-旦某个情报员开
始搜集情报,他的危险值就会持续增加,每天增加1点危险值(开始搜集情报的当天危险值仍为0,第2天
危险值为1,第3天危险值为2,以此类推)。传递情报并不会使情报员的危险值增加。
为了保证传递情报的过程相对安全,每条情报都有一个风险控制值C。余特公司认为,参与传递这条情
报的所有情报员中,危险值大于C的情报员将对该条情报构成威胁。现在,奈特公司希望知道,对于每
个传递情报任务,参与传递的情报员有多少个,其中对该条情报构成威胁的情报员有多少个。
题解:
离线操作
建一棵树上的主席树,以时间为关键字。
代码:
#include<cstdio> #include<algorithm> using namespace std; int tot,rt,T,cnt,last[1000005],ls[10000005],rs[10000005],tree[10000005],root[1000005],val[1000005],f[1000005][20],dep[1000005]; struct node{ int to,next; }e[1000005]; struct node1{ int x,y,z,ti; }q[1000005]; void add(int a,int b){ e[++cnt].to=b; e[cnt].next=last[a]; last[a]=cnt; } int lca(int x,int y){ if (dep[x]<dep[y]) swap(x,y); for (int i=19; i>=0; i--){ int to=f[x][i]; if (dep[to]>=dep[y]) x=to; } if (x==y) return x; for (int i=19; i>=0; i--){ int fx=f[x][i],fy=f[y][i]; if (fx!=fy) x=fx,y=fy; } return f[x][0]; } void dfs(int x,int fa){ f[x][0]=fa; for (int i=0; i<19; i++) f[x][i+1]=f[f[x][i]][i]; for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (V==fa) continue; dep[V]=dep[x]+1; dfs(V,x); } } void insert(int &now,int pre,int l,int r,int x){ now=++cnt; if (l==r){ tree[now]++; return; } ls[now]=ls[pre],rs[now]=rs[pre]; int mid=(l+r)>>1; if (x<=mid) insert(ls[now],ls[pre],l,mid,x); else insert(rs[now],rs[pre],mid+1,r,x); tree[now]=tree[ls[now]]+tree[rs[now]]; } void solve(int x,int fa){ if (val[x]) insert(root[x],root[fa],1,T,val[x]); else root[x]=root[fa]; for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (V==fa) continue; solve(V,x); } } int query(int now,int l,int r,int x){ if (!now) return 0; x=min(x,r); if (x<l) return 0; if (l==r) return tree[now]; int mid=(l+r)>>1; if (x>mid) return tree[ls[now]]+query(rs[now],mid+1,r,x); else return query(ls[now],l,mid,x); } int main(){ int n; scanf("%d",&n); for (int i=1; i<=n; i++){ int x; scanf("%d",&x); if (x) add(x,i); else rt=i; } dep[rt]=1; dfs(rt,0); cnt=0; scanf("%d",&T); for (int ti=1; ti<=T; ti++){ int k; scanf("%d",&k); if (k==1){ int x,y,z; scanf("%d%d%d",&x,&y,&z); q[++tot].x=x; q[tot].y=y; q[tot].z=ti-z-1; } else{ int x; scanf("%d",&x); val[x]=ti; } } solve(rt,0); for (int i=1; i<=tot; i++){ int x=q[i].x,y=q[i].y,z=q[i].z; int LCA=lca(x,y); int ans1=query(root[x],1,T,z); int ans2=query(root[y],1,T,z); int ans3=query(root[LCA],1,T,z); int ans4=query(root[f[LCA][0]],1,T,z); printf("%d %d ",dep[x]+dep[y]-dep[LCA]-dep[f[LCA][0]],ans1+ans2-ans3-ans4); } return 0; }