CF 1009 F Dominant Indices —— 长链剖分+指针

题目:http://codeforces.com/contest/1009/problem/F

也可以用 dsu on tree 的做法,全局记录一个 dep,然后放进堆里,因为字典序要最小,所以再记一个第二关键字 dep[u];

长链剖分是 O(n) 的,因为如果 O(1) 继承重儿子(长儿子),对其他儿子枚举长度,那么每个点只会在向上第一次合并到重儿子时被枚举一次,所以总体 O(n);

然而不能开 f[1e6][1e6] 的数组,考虑到因为自己继承重儿子,所以数组有很大一部分是共用的,如果真的共用,数组总长度就是长链长度的和(每条长链只在顶端被开出来),也就是 n;

所以用指针,f[x] 指向数组 tmp 中的一个位置,对应 f[x][0] 。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=1e6+5;
int n,hd[xn],ct,to[xn<<1],nxt[xn<<1],dep[xn],d[xn],son[xn],ans[xn];
int tmp[xn],*f[xn],*id=tmp;
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return f?ret:-ret;
}
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
void dfs(int x,int fa)
{
  dep[x]=d[x]=dep[fa]+1;//d[x]=dep[x]
  for(int i=hd[x],u;i;i=nxt[i])
    {
      if((u=to[i])==fa)continue;
      dfs(u,x);
      if(d[u]>d[x])son[x]=u,d[x]=d[u];
    }
}
void dfsx(int x,int fa)
{
  f[x][0]=1;
  if(son[x])f[son[x]]=f[x]+1,dfsx(son[x],x),ans[x]=ans[son[x]]+1;
  for(int i=hd[x],u;i;i=nxt[i])
    {
      if((u=to[i])==fa||u==son[x])continue;
      f[u]=id; id+=d[u]-dep[u]+1; dfsx(u,x);
      for(int j=0;j<=d[u]-dep[u];j++)
    {
      f[x][j+1]+=f[u][j];
      if(f[x][j+1]>f[x][ans[x]]||(f[x][j+1]==f[x][ans[x]]&&j+1<ans[x]))
        ans[x]=j+1;//f[x][ans[x]]!!
    }
    }
  if(f[x][ans[x]]==1)ans[x]=0;//cnt=1
}
int main()
{
  n=rd();
  for(int i=1,x,y;i<n;i++)x=rd(),y=rd(),add(x,y),add(y,x);
  dfs(1,0); f[1]=id; id+=d[1]; dfsx(1,0);//f[1]
  for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
  return 0;
}

 

posted @ 2018-11-26 10:37  Zinn  阅读(216)  评论(0)    收藏  举报