树上 L C S LCS LCS,强制根必须在 L C S LCS LCS中
数据范围: n l o g n nlogn nlogn
md要不是最后那句话我这道题绝对是最快最优解,艹
首先这就是一道二维偏序嘛(一维是权值,另一维是 d f n dfn dfn),所以我们按 d f s dfs dfs序做 L C S LCS LCS就行了啦
那第二个限制条件咋搞?
先查询,再放入根,就保证了啦QwQ
时间复杂度?疑似 O ( n l o g n ) O(nlogn) O(nlogn)然而理论上 O ( n 2 l o g n ) O(n^2logn) O(n2logn),实际上远远达不到呀2333
当然你也可以打启发式合并就稳稳的双log了2333
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include
#include
#include
#include
#include
#define N 100010
using namespace std;int n,fa[N],a[N],m,ans[N],tot;
vector<int>son[N];
inline long long read()
{
char c;int f=0,d=1;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
struct xds
{
int ls[N*200],rs[N*200],sum[N*200],rt[N];
inline int merge(int a,int b,int l=1,int r=n)
{
if(!a||!b) return a^b;
sum[a]=max(sum[a],sum[b]);
if(l==r) return a;
int mid=l+r>>1;
ls[a]=merge(ls[a],ls[b],l,mid);
rs[a]=merge(rs[a],rs[b],mid+1,r);
return a;
}
inline void insert(int &o,int pos,int val,int l=1,int r=n)
{
if(!o) o=++tot;
sum[o]=max(sum[o],val);
if(l==r) return;
int mid=l+r>>1;
if(pos<=mid) insert(ls[o],pos,val,l,mid);
else insert(rs[o],pos,val,mid+1,r);
return;
}
inline int query(int o,int ql,int qr,int l=1,int r=n)
{
if(!o) return 0;
if(l>=ql&&r<=qr) return sum[o];
int mid=l+r>>1,ans=-1;
if(ql<=mid) ans=query(ls[o],ql,qr,l,mid);
if(qr>mid) ans=max(ans,query(rs[o],ql,qr,mid+1,r));
return ans;
}
}tree;
inline void dfs(int x,int fa)
{
for(register int i=0;i<son[x].size();i++)
{
int y=son[x][i];
if(y==fa) continue;
dfs(y,fa);
tree.rt[x]=tree.merge(tree.rt[x],tree.rt[y]);
}
ans[x]=tree.query(tree.rt[x],1,a[x])+1;
tree.insert(tree.rt[x],a[x],ans[x]);
return;
}
signed main()
{
n=read();read();
for(register int i=2;i<=n;i++) fa[i]=read(),son[fa[i]].push_back(i);
for(register int i=1;i<=n;i++) a[i]=read();
dfs(1,0);
for(register int i=1;i<=n;i++) printf("%d ",ans[i]);
}