链接:https://ac.nowcoder.com/acm/problem/20570
来源:牛客网
输出描述:
对于每个传递情报任务输出一行,应包含两个整数,分别是参与传递情报的情报员个数和对该条情报构成威胁的情报员个数。
输出的行数应等于传递情报任务的个数,每行仅包含两个整数,用一个空格隔开。输出不应包含多余的空行和空格。
示例1
输入
复制
7
0 1 1 2 2 3 3
6
1 4 7 0
2 1
2 4
2 7
1 4 7 1
1 4 7 3
输出
复制
5 0
5 2
5 1
具体解释看代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=2e5+100;
struct node{
int l;
int r;
int num;
}p[maxx*40];
struct edge{
int to,next;
}e[maxx<<1];
struct ddd{
int x,y,t;
}q[maxx];
int head[maxx<<1],dp[maxx][26];
int root[maxx],deep[maxx],val[maxx];
int n,m,tot,rt,ror;
/*------------事前准备-------------*/
inline void init()
{
memset(dp,0,sizeof(dp));
memset(val,0,sizeof(val));
memset(head,-1,sizeof(head));
tot=ror=0;
}
inline void add(int u,int v)
{
e[tot].to=v,e[tot].next=head[u],head[u]=tot++;
}
/*----------主席树-----------*/
inline int build(int l,int r)
{
int cur=++ror;
p[cur].num=0;
if(l==r) return cur;
int mid=l+r>>1;
p[cur].l=build(l,mid);
p[cur].r=build(mid+1,r);
return cur;
}
inline int update(int rot,int l,int r,int pos)
{
int cur=++ror;
p[cur]=p[rot];
p[cur].num++;
if(l==r) return cur;
int mid=l+r>>1;
if(pos<=mid) p[cur].l=update(p[rot].l,l,mid,pos);
else p[cur].r=update(p[rot].r,mid+1,r,pos);
return cur;
}
inline int query(int lrot,int rrot,int frot,int ffrot,int l,int r,int pos)
{
if(l>pos) return 0;
if(r<=pos) return p[lrot].num+p[rrot].num-p[frot].num-p[ffrot].num;//点差分
int mid=l+r>>1;
int ret=0;
if(pos>=l) ret+=query(p[lrot].l,p[rrot].l,p[frot].l,p[ffrot].l,l,mid,pos);
if(pos>mid) ret+=query(p[lrot].r,p[rrot].r,p[frot].r,p[ffrot].r,mid+1,r,pos);
return ret;
}
/*------------dfs------------*/
inline void dfs(int u,int f)
{
deep[u]=deep[f]+1;
dp[u][0]=f;
for(int i=1;i<=25;i++)
{
if(dp[u][i-1]) dp[u][i]=dp[dp[u][i-1]][i-1];
else break;
}
root[u]=update(root[f],1,m,val[u]);
for(int i=head[u];i!=-1;i=e[i].next)
{
int to=e[i].to;
if(to==f) continue;
dfs(to,u);
}
}
/*-----------lca-----------*/
inline int get_lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
int tmp=deep[x]-deep[y];
for(int i=0;i<=25;i++)
{
if(tmp&(1<<i)) x=dp[x][i];
}
if(x==y) return x;
for(int i=25;i>=0;i--)
{
if(dp[x][i]!=dp[y][i])
{
x=dp[x][i];
y=dp[y][i];
}
}
return dp[x][0];
}
int main()
{
init();int x,op,y,c;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
if(x==0) rt=i;
add(x,i);add(i,x);
}
scanf("%d",&m);
for(int i=1;i<=n;i++) val[i]=m;//因为转化之后求得是小于等于某个值的数,所以初始化就要设置为最大值
int cnt=0;
for(int i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&x,&y,&c);
q[++cnt].x=x,q[cnt].y=y,q[cnt].t=i-c-1;//将所有查询操作保存下来。
}
else
{
scanf("%d",&x);
val[x]=i;
}
}
root[0]=build(1,m);
deep[0]=0;
dfs(rt,0);
for(int i=1;i<=cnt;i++)
{
x=q[i].x,y=q[i].y,c=q[i].t;
int Lca=get_lca(x,y);
printf("%d ",deep[x]+deep[y]-2*deep[Lca]+1);//节点个数。
printf("%d\n",query(root[x],root[y],root[Lca],root[dp[Lca][0]],1,m,c));
}
return 0;
}
努力加油a啊,(o)/~