bzoj 4448: [Scoi2015]情报传递

首先想到实际上是查询链上开始搜集的日子小于x的点的个数,然后yy了树上莫队做法。
其实这就是树上主席树的 裸题。
    
    
    
    
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
 
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
#define TR 4000010
#define N 200010
using namespace std;
struct yts { int x,t,ne;} e[2*N];
int ch[TR][2],sz[TR];
int day[N],root[N],fa[N][20],v[N],X[N],Y[N],C[N],dep[N];
int cnt,m,n,num,Ans=0;
 
void put(int x,int y)
{
num++; e[num].x=x; e[num].t=y;
e[num].ne=v[x]; v[x]=num;
}
 
void insert(int &i,int pre,int l,int r,int x)
{
i=++cnt; ch[i][0]=ch[pre][0]; ch[i][1]=ch[pre][1]; sz[i]=sz[pre]+1;
if (l==r) return;
int mid=(l+r)>>1;
if (x<=mid) insert(ch[i][0],ch[pre][0],l,mid,x);
else insert(ch[i][1],ch[pre][1],mid+1,r,x);
}
 
void query(int a,int b,int c,int d,int l,int r,int ql,int qr)
{
if (ql<=l&&r<=qr) { Ans+=sz[a]+sz[b]-sz[c]-sz[d]; return;}
int mid=(l+r)>>1;
if (ql<=mid) query(ch[a][0],ch[b][0],ch[c][0],ch[d][0],l,mid,ql,qr);
if (mid+1<=qr) query(ch[a][1],ch[b][1],ch[c][1],ch[d][1],mid+1,r,ql,qr);
}
 
void dfs(int x)
{
if (day[x]) insert(root[x],root[fa[x][0]],1,m,day[x]);
else root[x]=root[fa[x][0]];
for (int i=v[x];i;i=e[i].ne)
{
int y=e[i].t; dep[y]=dep[x]+1;
dfs(y);
}
}
 
void build_lca()
{
for (int j=1;j<=18;j++)
for (int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
 
int lca(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
int t=dep[x]-dep[y];
for (int i=18;i>=0;i--)
if (t&(1<<i)) x=fa[x][i];
if (x==y) return x;
for (int i=18;i>=0;i--)
if (fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
 
int main()
{
int rt;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&fa[i][0]);
if (!fa[i][0]) rt=i;
else put(fa[i][0],i);
}
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
int k;
scanf("%d",&k);
if (k==2) { int x; scanf("%d",&x); day[x]=i;}
else scanf("%d%d%d",&X[i],&Y[i],&C[i]);
}
dep[rt]=1; dfs(rt); build_lca();
for (int i=1;i<=m;i++)
if (X[i])
{
int z=lca(X[i],Y[i]),t=i-C[i]-1; printf("%d ",dep[X[i]]+dep[Y[i]]-2*dep[z]+1);
if (t<1) printf("0\n");
else
{
Ans=0; query(root[X[i]],root[Y[i]],root[z],root[fa[z][0]],1,m,1,t);
printf("%d\n",Ans);
}
}
return 0;
}

你可能感兴趣的:(bzoj 4448: [Scoi2015]情报传递)