标签:http 利用 color ext i++ cstring 自己的 for open
输出1行N 个整数,第个整数表示结点的观察员可以观察到多少人。
天天爱跑步这题自从去年提高组以来一直便是我的一块心里阴影。今天终于下定决心去填坑。
首先要求树上两点间的最短距离,毫无疑问要用到lca,此处懒惰的我用了最好写的倍增。
随后我们分析每一条路径(x,y),发现他能拆分成x->lca(x,y)和lca(x,y)->y两条链。
对于每一条x->lca(x,y)上的点now,他能观察到此人当且仅当deep[x]=deep[now]+w[now];
同样的对于每条lca(x,y)->y上的点,他能观察到此人当且仅当deep[y]-t=deep[now]-w[now];其中t为x->y的路径长度。
这时我们发现等式一边只与当前节点的deep有关,等式右边只与询问节点的deep和w有关,所以我们想到用一个桶打标记。
利用dfs序的性质,在一个点x入栈时,将deep[x]放入桶中,当lca(x,y)出栈时,使deep[x]出栈。
在y入栈时,将deep[y]-t+30000放入栈中(因为deep[y]-t可能<0),当lca(x,y)出栈时,使deep[y]-t+300000出栈。
对于每一个点,询问deep[now]+w[now]和deep[now]-w[now]+300000的桶中的数的个数。
但值得注意的是,这样统计对于路径有多余计算,所以要在该节点入栈时记录初始值,在该点出栈时记录结束值以此保证所有计算的点都经过该路径。
同时,当lca(x,y)能观察到从x出发的人时,这个人会被算两边,因此此处需要特判。
下面是AC代码:
1 #include<cstring> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<iostream> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 int n,m; 9 struct data 10 { 11 int to,next; 12 }a[600001],upj[600001],downa[600001],downj[600001]; 13 int c[300001]; 14 int headupj[300001],headdowna[300001],headdownj[300001]; 15 int cntupj,cntdowna,cntdownj; 16 int head[300001],cnt; 17 int f[300001][21]; 18 int deep[300001]; 19 int w[300001]; 20 int up[600101],down[600101]; 21 int ans[300001]; 22 void add(int u,int v){a[cnt].next=head[u];a[cnt].to=v;head[u]=cnt;cnt++;} 23 void addupj(int u,int v){upj[cntupj].next=headupj[u];upj[cntupj].to=v;headupj[u]=cntupj;cntupj++;} 24 void adddowna(int u,int v){downa[cntdowna].next=headdowna[u];downa[cntdowna].to=v;headdowna[u]=cntdowna;cntdowna++;} 25 void adddownj(int u,int v){downj[cntdownj].next=headdownj[u];downj[cntdownj].to=v;headdownj[u]=cntdownj;cntdownj++;} 26 void dfs(int now,int fa,int d) 27 { 28 deep[now]=d; 29 f[now][0]=fa; 30 //cout<<now<<endl; 31 for(int i=1;i<=20&&((1<<i)<=deep[now]);i++) f[now][i]=f[f[now][i-1]][i-1]; 32 for(int i=head[now];i>=0;i=a[i].next) 33 if(a[i].to!=fa) dfs(a[i].to,now,d+1); 34 } 35 int lca(int x,int y) 36 { 37 if(deep[x]<deep[y]) swap(x,y); 38 int t=deep[x]-deep[y]; 39 for(int i=20;i>=0;i--)if((1<<i)&t) x=f[x][i]; 40 for(int i=20;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; 41 return x==y?x:f[x][0]; 42 } 43 void dfs1(int now,int fa) 44 { 45 int u=up[w[now]+deep[now]],v=down[deep[now]-w[now]+300005]; 46 up[deep[now]]+=c[now]; 47 for(int i=headdowna[now];i>=0;i=downa[i].next) down[downa[i].to]++; 48 for(int i=head[now];i>=0;i=a[i].next) if(a[i].to!=fa) dfs1(a[i].to,now); 49 ans[now]=up[w[now]+deep[now]]+down[deep[now]-w[now]+300005]-u-v; 50 for(int i=headupj[now];i>=0;i=upj[i].next){up[upj[i].to]--;if(w[now]+deep[now]==upj[i].to) ans[now]--;} 51 for(int i=headdownj[now];i>=0;i=downj[i].next) down[downj[i].to]--; 52 } 53 int main() 54 { 55 //freopen("running.in","r",stdin); 56 //freopen("running.out","w",stdout); 57 memset(head,-1,sizeof(head)); 58 memset(headdowna,-1,sizeof(headdowna)); 59 memset(headdownj,-1,sizeof(headdownj)); 60 memset(headupj,-1,sizeof(headupj)); 61 scanf("%d%d",&n,&m); 62 for(int i=1;i<n;i++) 63 { 64 int u,v; 65 scanf("%d%d",&u,&v); 66 add(u,v); 67 add(v,u); 68 } 69 //cout<<1; 70 dfs(1,0,0); 71 /*for(int i=1;i<=n;i++) 72 for(int j=1;j<=20;j++) 73 cout<<i<<‘ ‘<<j<<‘ ‘<<f[i][j]<<endl; 74 /*for(int j=1;j<=20;j++) 75 for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1];*/ 76 for(int i=1;i<=n;i++) scanf("%d",&w[i]); 77 //cout<<1; 78 for(int i=1;i<=m;i++) 79 { 80 int x,y; 81 scanf("%d%d",&x,&y); 82 c[x]++; 83 int LCA=lca(x,y); 84 int t=deep[y]+deep[x]-2*deep[LCA]; 85 int d=deep[y]-t+300005; 86 addupj(LCA,deep[x]); 87 adddowna(y,d); 88 adddownj(LCA,d); 89 } 90 //cout<<1; 91 dfs1(1,0); 92 for(int i=1;i<n;i++) printf("%d ",ans[i]); 93 printf("%d",ans[n]); 94 }
标签:http 利用 color ext i++ cstring 自己的 for open
原文地址:http://www.cnblogs.com/wls001/p/7198575.html