洛谷P1600 天天爱跑步(NOIp2016)(BZOJ4719)
来源:互联网 发布:网络优化工作美篇 编辑:程序博客网 时间:2024/05/19 19:31
LCA
洛谷题目传送门
BZOJ题目传送门
炒鸡难的一题。。。码量还不小。。。
只想到拆成链,然而不知道怎么实现。。。只好认怂去看题解。。。
考虑每条路径,拆成两个链。一个从s到LCA,另一个从LCA到t。如果LCA有贡献的话就把答案-1(不然就算重啦)。
然后在每个s打个1,在LCA上打个-1,那么就变成求一个节点的子树和。
对于点
对于另一条链类似,当
LCA的话我用的是Tarjan,时间复杂度
当然倍增也是可以的。
代码:
#include<cstdio>#include<cstring>#include<vector>#include<algorithm>#define MAXN 300000#define MAXM 600000using namespace std;struct edge{ int next,to; };struct route{ int s,t,lca,dis; };int n,m,k,md;int w[MAXN+5],h1[MAXN+5],h2[MAXN+5],fa[MAXN+5],depth[MAXN+5],num[MAXN+5],ans[MAXN+5],t[MAXN+5],tt[MAXM+5];edge ed[MAXM*2+5];route p[MAXN+5];vector <int> t1[MAXN+5],t2[MAXN+5],t3[MAXN+5];bool f[MAXN+5];inline char readc(){ static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,100000,stdin); if (l==r) return EOF; return *l++;}inline int _read(){ int num=0; char ch=readc(); while (ch<'0'||ch>'9') ch=readc(); while (ch>='0'&&ch<='9') { num=num*10+ch-48; ch=readc(); } return num;}void addedge(int x,int y,int *h){ ed[++k].next=h[x]; ed[k].to=y; h[x]=k;}int findfather(int x){ if (fa[x]==x) return x; return fa[x]=findfather(fa[x]);}void Tarjan(int x,int father){ fa[x]=x; f[x]=true; for (int i=h2[x];i;i=ed[i].next){ int v=ed[i].to; if (x==p[v].s&&f[p[v].t]) p[v].lca=findfather(p[v].t); if (x==p[v].t&&f[p[v].s]) p[v].lca=findfather(p[v].s); } for (int i=h1[x];i;i=ed[i].next) if (ed[i].to!=father){ int v=ed[i].to; depth[v]=depth[x]+1; Tarjan(v,x); fa[v]=x; }}void dfs1(int x,int father){ int now=w[x]+depth[x],l; if (now<=md) l=t[now]; for (int i=h1[x];i;i=ed[i].next) if (ed[i].to!=father) dfs1(ed[i].to,x); t[depth[x]]+=num[x]; if (now<=md) ans[x]=t[now]-l; int len=t1[x].size(); for (int i=0;i<len;i++) t[depth[t1[x][i]]]--;}void dfs2(int x,int father){ int now=depth[x]-w[x]+MAXN,l; l=tt[now]; for (int i=h1[x];i;i=ed[i].next) if (ed[i].to!=father) dfs2(ed[i].to,x); int len=t2[x].size(); for (int i=0;i<len;i++) tt[MAXN+t2[x][i]]++; len=t3[x].size(); ans[x]+=tt[now]-l; for (int i=0;i<len;i++) tt[MAXN+t3[x][i]]--;}int main(){ n=_read(); m=_read(); for (int i=1;i<n;i++){ int u=_read(),v=_read(); addedge(u,v,h1); addedge(v,u,h1); } for (int i=1;i<=n;i++) w[i]=_read(); for (int i=1;i<=m;i++){ p[i].s=_read(); p[i].t=_read(); num[p[i].s]++; addedge(p[i].s,i,h2); addedge(p[i].t,i,h2); } Tarjan(1,0); for (int i=1;i<=n;i++) md=max(md,depth[i]); for (int i=1;i<=m;i++){ p[i].dis=depth[p[i].s]+depth[p[i].t]-depth[p[i].lca]*2; t1[p[i].lca].push_back(p[i].s); } dfs1(1,0); for (int i=1;i<=m;i++){ t2[p[i].t].push_back(depth[p[i].t]-p[i].dis); t3[p[i].lca].push_back(depth[p[i].t]-p[i].dis); } dfs2(1,0); for (int i=1;i<=m;i++) if (depth[p[i].s]-w[p[i].lca]==depth[p[i].lca]) ans[p[i].lca]--; for (int i=1;i<=n;i++) printf("%d ",ans[i]); return 0;}
阅读全文
1 0
- 洛谷P1600 天天爱跑步(NOIp2016)(BZOJ4719)
- bzoj4719/洛谷1600 noip2016天天爱跑步
- BZOJ4719 [Noip2016]天天爱跑步
- bzoj4719 [Noip2016]天天爱跑步
- 【NOIP2016】bzoj4719 天天爱跑步
- 【BZOJ4719】[Noip2016]天天爱跑步
- BZOJ4719 [Noip2016]天天爱跑步
- bzoj4719 [Noip2016]天天爱跑步
- bzoj4719 [Noip2016]天天爱跑步
- bzoj4719 [Noip2016]天天爱跑步
- bzoj4719: [Noip2016]天天爱跑步
- 【bzoj4719】[Noip2016]天天爱跑步
- NOIP2016 && bzoj4719天天爱跑步
- 洛谷 P1600 天天爱跑步
- [bzoj4719][树链剖分][Noip2016]天天爱跑步
- [题解]bzoj4719 NOIP2016天天爱跑步
- BZOJ4719(NOIP2016)[天天爱跑步]--LCA+DFS
- P1600 天天爱跑步
- php连接PostgreSQL错误Call to undefined function pg_connect()
- iPhone identifier对应设备类型(含iPhone 8/iPhone X)
- 12进制和20进制计数器
- iOS开发断点调试高级技巧
- SpringMVC 测试 mockMVC
- 洛谷P1600 天天爱跑步(NOIp2016)(BZOJ4719)
- Vue笔记
- 【笔记】最大全0 or 1子矩阵
- C++ primer 数组和指针
- GAN调试记录
- 什么是前端模块化?前端模块化开发到底有无必要
- thread 线程执行顺序
- 电磁波中的波段划分:L波段、S波段、C波段、X波段、Ku波段、K波段、Ka波段
- 1 redis在spring中的配置及java代码实现 2 redis在java项目中的使用