天天爱跑步
来源:互联网 发布:登陆淘宝网店 编辑:程序博客网 时间:2024/04/28 23:08
天天爱跑步
(File IO): input:running.in output:running.out
Time Limits: 2s Memory Limits: 512MB
Description
Input
Output
Sample Input
Sample Input1:
6 32 31 21 44 54 60 2 5 1 2 31 51 32 6
Sample Input2:
5 31 22 32 41 50 1 0 3 03 11 45 5
Sample Output
Sample Output1:
2 0 0 1 1 1
Sample Output2:
1 2 1 0 1
Hint
Data Constraint
解题思路
以1为根遍历一遍,求出每一个点的的层数fl[i]
对于每一对s,t都会有他们的lca,则s到t的长度len为fl[s]+fl[t]-2fl[lca]我们可以分为s->lca,lca->t考虑:
对于路径s->lca的点d如图①,在第w[d]个时间点上到达需满足
对于路径lca->t的点d如图②,在第w[d]个时间点上到达需满足
搜完以i为根的子树,我们可以用两个桶分别表示:
1. now[0][x] 为i的子树中,所有能经过i的起点s,fl[s]=x的数量
2. now[1][x] 为i的子树中,所有能经过i的终点t,len-fl[t]=x的数量
则x的节点的答案为now[0][w[x]+fl[x]]-搜完i的子树前的now[0][w[x]-fl[x]]+now[1][w[x]-fl[x]]-搜完i的子树前的now[1][w[x]-fl[x]]
Codes
#include<cstring>#include<cstdio>#define lim 100000000#define ad 600010 using namespace std;int to[ad*2],nex[ad*2],fir[ad],las[ad],w[ad],n,m,len;int data[ad],fl[ad],num[2][ad*2],top,f[20][ad],vfir[2][ad*2],vlas[2][ad*2],vnex[2][ad*2],sum[ad],vtot[2],vv[2][ad*2];bool bz[300000];void link(int x,int y){ top++; to[top]=y;nex[top]=0; if(fir[x])nex[las[x]]=top;else fir[x]=top; las[x]=top;}void swap(int &a,int &b){int c=a;a=b;b=c;}void vlink(int x,int s,int v){ int a,b,c,d,e,f; int k=++vtot[s]; vv[s][k]=v; vnex[s][k]=0; if(vfir[s][x])vnex[s][vlas[s][x]]=k;else vfir[s][x]=k; vlas[s][x]=k; a=x;b=s;c=v; d=vv[s][k]; e=vfir[s][x]; f=vlas[s][x];}void work(int x){ int s1=num[0][fl[x]+w[x]+ad],s2=num[1][w[x]-fl[x]+ad]; for(int j=0;j<2;j++) for(int i=vfir[j][x];i;i=vnex[j][i]) { int xx=vv[j][i]; if(xx<=lim)num[j][xx]++; } for(int i=fir[x];i;i=nex[i]) { if(bz[to[i]])continue; bz[to[i]]=1; work(to[i]); } for(int j=0;j<2;j++) for(int i=vfir[j][x];i;i=vnex[j][i]) { int xx=vv[j][i]; if(xx>lim)num[j][xx-lim]--; } sum[x]+=num[0][ad+fl[x]+w[x]]-s1; sum[x]+=num[1][w[x]-fl[x]+ad]-s2;}int main(){ freopen("running.in","r",stdin); freopen("running.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); link(x,y),link(y,x); } int h=0,t=1; data[1]=1; fl[1]=0;bz[1]=1; while(h<t) { int now=data[++h]; for(int i=fir[now];i;i=nex[i]) { int x=to[i]; if(!bz[x]) { bz[x]=1; f[0][x]=now; fl[x]=fl[now]+1; data[++t]=x; } } } for(int i=1;i<=n;i++)scanf("%d",&w[i]); for(int j=1;j<20;j++) for(int i=1;i<=n;i++) if(fl[i]>=(1<<j)) { f[j][i]=f[j-1][f[j-1][i]]; } for(int i=1;i<=m;i++) { int s,t,lca,tx,ty,temp,co=0; scanf("%d%d",&s,&t); if(s==t) { if(w[s]==0)sum[s]++; continue; } tx=s,ty=t; if(fl[tx]>fl[ty])swap(tx,ty); temp=fl[ty]-fl[tx]; while(temp) { if(temp&1)ty=f[co][ty]; temp>>=1; co++; } if(tx==ty) { lca=tx; }else { for(int j=19;j+1;j--) { if((1<<j)>fl[tx])continue; if(f[j][ty]!=f[j][tx]) { tx=f[j][tx]; ty=f[j][ty]; } } lca=f[0][tx]; } len=fl[s]+fl[t]-fl[lca]*2; if(w[lca]==fl[s]-fl[lca])sum[lca]++; if(s!=lca) { vlink(s,0,ad+fl[s]); vlink(lca,0,ad+fl[s]+lim); } if(t!=lca) { vlink(t,1,ad+len-fl[t]); vlink(lca,1,ad+len-fl[t]+lim); } } memset(bz,0,sizeof(bz)); bz[1]=1; work(1); for(int i=1;i<=n;i++)printf("%d ",sum[i]);}
0 0
- 天天爱跑步
- NOIP2016 天天爱跑步
- P1600 天天爱跑步
- [UOJ261]天天爱跑步
- [NOIP2016]天天爱跑步
- [NOIP2016]天天爱跑步
- NOIP2016 天天爱跑步
- NOIP2016 天天爱跑步
- LCA 天天爱跑步
- 天天爱跑步NOIP
- 天天爱跑步
- 【NOIP2016】天天爱跑步
- noip2016天天爱跑步
- 跑步爱天天
- NOIP2016天天爱跑步
- NOIP2016 天天爱跑步
- BZOJ4719 [Noip2016]天天爱跑步
- NOIP 2016 天天爱跑步
- 关于PV操作
- 基于行的逻辑
- TCP UDP IP HTTP之间的联系
- 康拓展开
- Android中微信支付申请、集成、出包等整个过程
- 天天爱跑步
- Codeforces 734E. Anton and Tree By Assassin 缩点+树的最大直径
- 计算机中的定点和浮点表示
- Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式)介绍
- ural 1881
- JDBC基本操作(Statement,PreparedStatement,Connection,Transaction等)
- nginx源代码分析 - 启动(八) 避免epoll_wait惊群
- react-redux 之 connect 方法详解
- Swift3.0后Alamofire报错的解决方法