花花的森林,嗯,这是一篇正经的题解。

模拟考的时候没有看出来要怎么求啊,暴力地树形DP、换根、合并、求直径。居然也险险地拿到了80分,不过我们要正经地想正解。

容易想到我们可以让时光倒流,让空间扭转,离线地从最后一次操作往前,这样删边就变成加边了(合并总比拆开好做吧)

首先,我们要知道,两棵树合并后,新直径的两个端点一定是原来两棵树的两个直径的四个不同端点中的某两个(为什么?),自己画一下图,思考证明一下,这个结论并不难得出。

所以说合并时的新直径就只会有六种即 C(4,2),那么我们分别求出这六个直径的值(当然原本的两种不用求),用最大的作为新树的直径就好啦~,并且记下此时的两个端点。

那要怎么求直径啊~?

当然是倍增啦。

可是可是,我们都把树拆成一棵棵了,怎么倍增啊,合并后不是还要重新算一次倍增的数组吗?

我们可以在原树上倍增呀,没必要真的把树拆了(如果题目让你做什么你就做什么,一定会被带离正解的),在一棵树上,两点之间的简单路径是唯一的。

(那你真是个小机灵鬼~)

然后合并就用并查集维护。

哦对了,还有一个细节,从后往前做我们会遇到除法的问题(难不成你要循环一遍整个森林求一次ans吗)所以在模质数的意义下,使用费马小定理求逆元来进行除法。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<algorithm>
  6
  7 #define For(i,a,b) for(register int i=a;i<=b;++i)
  8 #define Dwn(i,a,b) for(register int i=a;i>=b;--i)
  9 #define Re register
 10 #define Pn putchar('\n')
 11 #define llg long long
 12 using namespace std;
 13 const int N=1e5+10,md=1e9+7;
 14 llg a[N],ans=1,dt[N],pt[N][2],fn[N];
 15 int head[N],nxt[N*2],v[N*2],cnt=1;
 16 int pa[N],sz[N],n,m,x,y,Q[N];
 17 int f[N][25];
 18 llg d[N][25];
 19 struct EDG{
 20     int a,b;
 21 }ed[N];
 22 inline void read(int &v){
 23     v=0;
 24     char c=getchar();
 25     while(c<'0'||c>'9')c=getchar();
 26     while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar();
 27 }
 28 inline void read(llg &v){
 29     v=0;
 30     char c=getchar();
 31     while(c<'0'||c>'9')c=getchar();
 32     while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar();
 33 }
 34 void write(llg x){
 35     if(x>9)write(x/10);
 36     int xx=x%10;
 37     putchar(xx+'0');
 38 }
 39 int find(int x){
 40     int r=x;
 41     while(pa[r]!=r)r=pa[r];
 42     int i,j;
 43     i=x;
 44     while(pa[i]!=r){
 45         j=pa[i]; pa[i]=r; i=j;
 46     }
 47     return r;
 48 }
 49 void add(int ux,int vx){
 50     cnt++;
 51     nxt[cnt]=head[ux]; head[ux]=cnt; v[cnt]=vx;
 52     cnt++;
 53     nxt[cnt]=head[vx]; head[vx]=cnt; v[cnt]=ux;
 54 }
 55 llg Qsm(llg x,int k){
 56     llg ans=1;
 57     while(k){
 58         if(k&1)ans=(ans*x)%md;
 59         x=(x*x)%md;
 60         k>>=1;
 61     }
 62     return ans;
 63 }
 64
 65 int dep[N];
 66 void DFS(int x,int fa){
 67
 68     for(Re int i=head[x];i;i=nxt[i]){
 69         int vv=v[i];
 70
 71         if(vv==fa)continue;
 72
 73         f[vv][0]=x; d[vv][0]=a[vv];
 74         dep[vv]=dep[x]+1;
 75
 76         DFS(vv,x);
 77     }
 78 }
 79
 80 llg getDis(int x,int y){
 81     llg as=0;
 82     if(dep[x]<dep[y])swap(x,y);
 83
 84     Dwn(b,20,0)if(f[x][b]!=-1){
 85         if(dep[f[x][b]]>=dep[y]){
 86             as+=d[x][b];  x=f[x][b];
 87         }
 88     }
 89
 90     if(x==y)return as+a[x];
 91     Dwn(b,20,0)if(f[x][b]!=-1&&f[y][b]!=-1&&f[x][b]!=f[y][b]){
 92         as+=d[x][b]; as+=d[y][b];
 93         x=f[x][b]; y=f[y][b];
 94     }
 95     as+=d[x][0]; as+=d[y][0];
 96
 97     return as+a[f[x][0]];
 98 }
 99
100 llg d00,d10,d01,d11,kd,dx=0,px1,px2;
101
102 int main(){
103     freopen("forest.in","r",stdin);
104     freopen("forest.out","w",stdout);
105     read(n);
106     For(i,1,n){
107         read(a[i]);
108         ans=(ans*a[i])%md;
109         pt[i][0]=pt[i][1]=i; dt[i]=a[i];
110     }
111     For(i,1,n-1){
112         read(ed[i].a); read(ed[i].b);
113         add(ed[i].a,ed[i].b);
114     }
115     memset(f,-1,sizeof(f));
116
117     DFS(1,0);
118
119     For(b,1,20) For(i,1,n){
120         if(f[i][b-1]==-1)continue;
121
122         f[i][b]= f[ f[i][b-1] ][b-1];
123         d[i][b]= d[ f[i][b-1] ][b-1]+d[i][b-1];
124     }
125
126     For(i,1,n)pa[i]=i;
127
128     For(i,1,n-1)read(Q[i]);
129     fn[n]=ans;
130     Dwn(i,n-1,1){
131         int qs=Q[i];
132         x=ed[qs].a; y=ed[qs].b;
133         int pax=find(x),pay=find(y);
134
135         ans=(ans*Qsm(dt[pax],md-2))%md;
136         ans=(ans*Qsm(dt[pay],md-2))%md;
137
138         if(dt[pax]>dt[pay]){
139             dx=dt[pax]; px1=pt[pax][0]; px2=pt[pax][1];
140         }else{
141             dx=dt[pay]; px1=pt[pay][0]; px2=pt[pay][1];
142         }
143
144         d00=getDis(pt[pax][0],pt[pay][0]);
145         if(d00>dx)dx=d00,px1=pt[pax][0],px2=pt[pay][0];
146
147         d10=getDis(pt[pax][1],pt[pay][0]);
148         if(d10>dx)dx=d10,px1=pt[pax][1],px2=pt[pay][0];
149
150         d01=getDis(pt[pax][0],pt[pay][1]);
151         if(d01>dx)dx=d01,px1=pt[pax][0],px2=pt[pay][1];
152
153         d11=getDis(pt[pax][1],pt[pay][1]);
154         if(d11>dx)dx=d11,px1=pt[pax][1],px2=pt[pay][1];
155
156         pt[pax][0]=px1; pt[pax][1]=px2;
157
158         dt[pax]=dx;
159         ans=(ans*dx)%md;
160         pa[pay]=pax;
161         fn[i]=ans;
162     }
163     For(i,1,n){
164         write(fn[i]); Pn;
165     }
166     return 0;
167 }

转载于:https://www.cnblogs.com/HLAUV/p/9894047.html

花花的森林(倍增,LCA相关推荐

  1. 洛谷1967 火车运输 kruskal求最大生成树 倍增LCA维护最小值

    传送门 其实NOIP某些年的第三题也并不是很难嘛... 题目分析: 题目中要求求出某两点之间可以运输的最大重量,也就是这两个点的某条路径上边权最小的边的权值的最大值 很显然,题目中的运输最大重量与选择 ...

  2. HDU - 3078 Network 倍增LCA

    倍增lca,把路径上点全部拉出来拍个序输出第k大就过了. 不知道怎么过的,咱也不敢问. #include<stdio.h> #include<string.h> #includ ...

  3. BZOJ 2144 跳跳棋(神仙建模题,倍增 LCA,二分)【BZOJ修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2144 是 hydro 的 BZOJ ...

  4. JZOJ 5286. 【NOIP2017提高A组模拟8.16】花花的森林

    Description Input Output Sample Input 3 1 2 3 1 2 1 3 2 1 Sample Output 6 9 6 Data Constraint Hint S ...

  5. 洛谷T1967 货车运输 Kruskal最大生成树倍增LCA

    这题的题意是:对于每组x.y,求x到y路径上最小边权的最大值. 于是可以使用最大生成树,因为最大生成树满足性质:生成树中最小边权最大,且任意两点间路径上最小边权最大. 有了树之后,要求路径,那就要考虑 ...

  6. [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MB Submit: 2131  Solved: 865 [Submit][Sta ...

  7. NOIP2013 D1T3 货车运输 倍增LCA OR 并查集按秩合并

    思路: Kruskal求最大生成树+倍增LCA // by SiriusRen #include <cstdio> #include <cstring> #include &l ...

  8. 【Codeforces613D】Kingdom and its Cities【虚树】【Tree DP】倍增lca

    http://codeforces.com/problemset/problem/613/D 题意: 给出n个点的树,有q个询问,每次询问给出k个重要的点,问至少删掉多少个非重要的点,使得这个重要的点 ...

  9. 2019长沙学院新生赛(A水,B水,C(整除分块),D水,E(巧数学),F(二分+bfs),H(换根dp),I(线段树)J(dp+倍增+lca))

    A-XOR SUM 通过简单观察得知连续四个数的异或值就是等于0,暴力找出左区间和右区间就可以了,最多跑四个单位 0^1^2^3==0   4^5^6^7=0 #include<bits/std ...

最新文章

  1. Artificial Intelligence Yourself
  2. Git每次推送时都会询问用户名
  3. 基于fiddler的网络爬虫校园网自动登陆系统
  4. 使用DiskFileItemFactory 实现文件上传 ,设定缓冲区大小和存放临时文件目录。
  5. IOS 应用中从竖屏模式强制转换为横屏模式
  6. java 使用logback进行日志输出
  7. 各种编译环境中如何为C++添加命令行参数(Command-line parameter)
  8. 如何使用python进行批处理
  9. Python模块Pygame安装
  10. 深度学习 --- 随机神经网络详解(玻尔兹曼机学习算法、运行算法)
  11. Hadoop、Spark等5种大数据框架对比,你的项目该用哪种?
  12. Qt制作贪吃蛇小游戏
  13. graphviz安装
  14. 西湖大学博导:都说不唯论文,那我们发表论文是为了什么?
  15. 【正则】详解python正则表达式之re.group()用法
  16. 服装尺寸 html,超完整的各种服装尺寸对照表,总有你需要的
  17. html里怎么计算梯形周长公式是什么,梯形的周长怎么计算 梯形周长计算公式
  18. win10 + MuMu 安装与配置frida环境
  19. Matlab含新能源(风电光伏)和多类型电动汽车配电网风险评估
  20. tomcat调优-占用内存太多

热门文章

  1. 前端更新需要清空浏览器缓存_js清除浏览器缓存的几种方法
  2. 思科N9K交换机配置QOS
  3. 北京同创蓝天的全景航拍技术如何?应用在哪些方面呢?
  4. MySQL高可用架构-MMM环境部署记录
  5. 培训班出来,碰到查学历,哎宝宝苦。
  6. 怎么用html实现QQ代挂功能,如何给自己的代挂网、代刷网、底部添加腾讯云智服客服代码...
  7. Lua 5.1.3源代码分析之词法分析[1]
  8. Java包的简单理解
  9. 低代码开发平台是什么?
  10. 如何在Windows上搭建web站点,并发布到公网?1-1