[启发式合并 DP] Atcoder ARC086E. Smuggling Marbles

来源:互联网 发布:超声波动物驱赶器,知乎 编辑:程序博客网 时间:2024/06/10 21:33

比赛的时候想到了每层独立,但是不会搞…

官方题解

好像学到了关于深度的信息启发式合并的次数是 O(n) 的…
还有deque这种神奇的东西……像我以前都是set加上各种外层的标记……

果然还是太弱了

#include <cstdio>#include <iostream>#include <algorithm>#include <queue>using namespace std;typedef pair<int,int> par;const int N=200010,P=1e9+7,inv2=P+1>>1;int n,cnt,G[N],dpt[N];struct edge{  int t,nx;}E[N];struct tp{  int x,y,z;  tp(){}  tp(int a,int b,int c):x(a),y(b),z(c){}};inline void addedge(int x,int y){  E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;}inline int Pow(int x,int y){  int ret=1;  for(;y;y>>=1,x=1LL*x*x%P) if(y&1) ret=1LL*ret*x%P;  return ret;}deque<tp> f[N];void dfs(int x){  int mx=0,smx=0;  for(int i=G[x];i;i=E[i].nx){    dfs(E[i].t); int v=E[i].t;    if(f[v].size()>mx) smx=mx,mx=f[v].size();    else smx=max(smx,(int)f[v].size());    if(f[v].size()>f[x].size()) swap(f[x],f[v]);    for(int j=0;j<f[v].size();j++){      tp cur;      cur.x=(1LL*f[x][j].x*f[v][j].y+1LL*f[v][j].x*f[x][j].y)%P;      cur.y=1LL*f[x][j].y*f[v][j].y%P;      cur.z=(1LL*f[x][j].x*f[v][j].x+1LL*f[x][j].x*f[v][j].z+1LL*f[x][j].y*f[v][j].z+1LL*f[x][j].z*f[v][j].x+1LL*f[x][j].z*f[v][j].y+1LL*f[x][j].z*f[v][j].z)%P;      f[x][j]=cur;    }  }  for(int i=0;i<smx;i++){    f[x][i].y=(f[x][i].y+f[x][i].z)%P;    f[x][i].z=0;  }  f[x].push_front(tp(inv2,inv2,0));}int main(){  scanf("%d",&n);  for(int i=1,x;i<=n;i++)    scanf("%d",&x),addedge(x,i);  dfs(0); int ans=0;  for(int i=0;i<f[0].size();i++)    ans=(ans+f[0][i].x)%P;  ans=1LL*ans*Pow(2,n+1)%P;  printf("%d\n",ans);  return 0;}