JZOJ 5286. 【NOIP2017提高A组模拟8.16】花花的森林
来源:互联网 发布:乒乓球直播软件 编辑:程序博客网 时间:2024/04/28 02:49
Description
Input
Output
Sample Input
3
1 2 3
1 2
1 3
2
1
Sample Output
6
9
6
Data Constraint
Hint
Solution
首先,我们要知道树中直径的一个性质:
对于两棵树,合并后的直径的两端点一定是之前两直径的四端点之二,证明显然。
看到这种可逆的操作问题,我们自然地想到要倒着做。
把断边转化成连边,变成两棵树的合并,并求其合并后的直径,
那么把之前的断点记录一下,用倍增 Lca
O(log N) 求出哪个值最大即可。其它树的值不用都计算,只需除以两个数的值、再乘回合并后的值即可(用逆元)。
总时间复杂度
O(N log N) 。
Code
#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int N=1e5+2,mo=1e9+7;struct data{ int x,y;}b[N],g[N],t;int tot;int a[N],q[N],f[N];int fa[N][17],len[N][17],dep[N];long long ans[N],v[N];int first[N],next[N<<1],en[N<<1];inline int read(){ int X=0,w=1; char ch=0; while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar(); return X*w;}inline void write(long long x){ if(x>9) write(x/10); putchar(x%10+'0');}inline void insert(int x,int y){ next[++tot]=first[x]; first[x]=tot; en[tot]=y;}inline int get(int x){ if(f[x]==x) return x; return f[x]=get(f[x]);}inline void dfs(int x){ dep[x]=dep[fa[x][0]]+1; for(int i=first[x];i;i=next[i]) if(en[i]!=fa[x][0]) { fa[en[i]][0]=x; len[en[i]][0]=a[en[i]]; dfs(en[i]); }}inline long long ksm(long long x,int y){ long long s=1; while(y) { if(y&1) s=s*x%mo; x=x*x%mo; y>>=1; } return s;}inline int lca(int x,int y){ if(dep[x]<dep[y]) swap(x,y); int sum=0; for(int i=log2(dep[x]);i>=0;i--) if(dep[fa[x][i]]>=dep[y]) sum+=len[x][i],x=fa[x][i]; if(x==y) return sum+a[x]; for(int i=log2(dep[x]);i>=0;i--) if(fa[x][i]!=fa[y][i]) sum+=len[x][i]+len[y][i],x=fa[x][i],y=fa[y][i]; sum+=len[x][0]+len[y][0]+a[fa[x][0]]; return sum;}int main(){ int n=read(); for(int i=ans[n]=1;i<=n;i++) { v[i]=a[i]=read(); ans[n]=ans[n]*a[i]%mo; g[i].x=g[i].y=f[i]=i; } for(int i=1;i<n;i++) { b[i].x=read(),b[i].y=read(); insert(b[i].x,b[i].y); insert(b[i].y,b[i].x); } dfs(1); for(int j=1;j<17;j++) for(int i=1;i<=n;i++) { fa[i][j]=fa[fa[i][j-1]][j-1]; len[i][j]=len[i][j-1]+len[fa[i][j-1]][j-1]; } for(int i=1;i<n;i++) q[i]=read(); for(int i=n-1;i;i--) { int x=b[q[i]].x,y=b[q[i]].y; int f1=get(x),f2=get(y); f[f1]=f2; ans[i]=ans[i+1]*ksm(v[f1],mo-2)%mo*ksm(v[f2],mo-2)%mo; long long mx=0; int s1=lca(g[f1].x,g[f2].x),s2=lca(g[f1].y,g[f2].y); int s3=lca(g[f1].x,g[f2].y),s4=lca(g[f1].y,g[f2].x); if(s1>s2) { if(s1>s3) { if(s1>s4) { mx=s1; t.x=g[f1].x,t.y=g[f2].x; }else { mx=s4; t.x=g[f1].y,t.y=g[f2].x; } }else { if(s3>s4) { mx=s3; t.x=g[f1].x,t.y=g[f2].y; }else { mx=s4; t.x=g[f1].y,t.y=g[f2].x; } } }else { if(s2>s3) { if(s2>s4) { mx=s2; t.x=g[f1].y,t.y=g[f2].y; }else { mx=s4; t.x=g[f1].y,t.y=g[f2].x; } }else { if(s3>s4) { mx=s3; t.x=g[f1].x,t.y=g[f2].y; }else { mx=s4; t.x=g[f1].y,t.y=g[f2].x; } } } if(v[f1]>mx) mx=v[f1],t=g[f1]; if(v[f2]>mx) mx=v[f2],t=g[f2]; ans[i]=ans[i]*mx%mo; v[f2]=mx; g[f2]=t; } for(int i=1;i<=n;i++) write(ans[i]),putchar('\n'); return 0;}
阅读全文
1 0
- JZOJ 5286. 【NOIP2017提高A组模拟8.16】花花的森林
- JZOJ 5286. 【NOIP2017提高A组模拟8.16】花花的森林 (Standard IO)
- 【NOIP2017提高A组模拟8.16】花花的森林
- 【jzoj5286】【NOIP2017提高A组模拟8.16】【花花的森林 】【时间倒流】
- 【JZOJ 5248】【NOIP2017提高A组模拟8.10】花花的聚会
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- JZOJ 5195. 【NOIP2017提高组模拟7.3】A
- JZOJ 100026. 【NOIP2017提高A组模拟7.7】图
- JZOJ 100030. 【NOIP2017提高A组模拟7.8】为了爱情
- jzoj. 100031. 【NOIP2017提高A组模拟7.9】外星密码
- JZOJ 100035【NOIP2017提高A组模拟7.10】区间
- JZOJ 100036 【NOIP2017提高A组模拟7.10】随机
- JZOJ 100037【NOIP2017提高A组模拟7.11】后缀数组
- JZOJ 100035. 【NOIP2017提高A组模拟7.10】区间
- JZOJ 100041. 【NOIP2017提高A组模拟7.12】列车调度
- JZOJ 100045. 【NOIP2017提高A组模拟7.13】好数
- JZOJ 100046. 【NOIP2017提高A组模拟7.14】收集卡片
- js实现分页
- poj 1651 Multiplication Puzzle
- Chunkize warning while installing gensim 疑难杂症
- Show Me the Money
- 国王游戏(贪心)
- JZOJ 5286. 【NOIP2017提高A组模拟8.16】花花的森林
- 魔戒(四维bfs)
- Angular2 使用 Observables From Other Sources
- WKWebView替换UIWebView
- 今日头条项目各种问题
- Mysql服务器丢失后的修复
- CodeForces
- NYOJ 36 最长公共子序列
- hdu 2204 Eddy's爱好(容斥原理)