JZOJ 5286. 【NOIP2017提高A组模拟8.16】花花的森林 (Standard IO)
5286. 【NOIP2017提高A组模拟8.16】花花的森林 (Standard IO)
Time Limits: 1000 ms Memory Limits: 131072 KB
Description
Input
Output
Sample Input
3
1 2 3
1 2
1 3
2
1
Sample Output
6
9
6
Data Constraint
Hint
题解
我们考虑倒着做,即最开始是一个包含了 n 棵只有一个点的树的森林,然后不断加边,最后得到一棵完整的树。这样我们只需能够快速求出两棵树合并后得到新树的直径即可解决这个问题。
设合并的两棵树是 Ta 和 Tb,合并后形成的新树是 T。记 Ta 的直径的两端点为 ua 和va,Tb 的直径的两端点为 ub 和 vb,则 T 的直径的两端点一定 ∈ {ua, ub, va, vb}(由反证法不难证明)。这样我们只需维护每个块的直径及直径的两端点。在合并两个块时,我们只需暴力求出 4 个点对之间的路径长度,进行比较即可。
在这个过程中我们需要除以原来两块的直径。在模的意义下,除以一个数等价于乘以这个数的逆元。时间复杂度为O(n2),期望得分 60 − 80 分。
我们考虑改进上面的做法,虽然有加边、删边操作,但事实上我们要求的点对之间的路
径长度都是原树上的路径。故我们可以通过对原树进行倍增预处理,每次在 O(logn) 的时间内求得点对间的最近公共祖先(lca),从而得到点对间的路径长度。
时间复杂度为O(nlogn),期望得分 100 分。
代码
#include<cstdio>
#include<algorithm>
#include<vector>
#define ll long long
#define mo 1000000007
#define UP 20
#define N 100010
using namespace std;
struct point{
long x,y;
void make(long x,long y)
{
this->x=x;
this->y=y;
}
}root[N],b[N];
long n;
long fa[N][UP+1],dep[N],father[N],w[N],a[N],len[N],c[N],out[N];
void init()
{ long i,j;
for(i=1;i<=n;i++){
for(j=1;(1<<j)<=dep[i];j++)
fa[i][j]=fa[fa[i][j-1]][j-1];
father[i]=i;
root[i].make(i,i);
w[i]=a[i];
}
}
long lca(long x,long y)
{ long up,xx=x,yy=y;
if(dep[x]>dep[y])
swap(x,y);
for(up=UP;up>=0;up--)
if(dep[y]-(1<<up)>=dep[x])
y=fa[y][up];
up=UP;
while(x!=y){
while(up>=0&&fa[x][up]==fa[y][up])
up--;
if(up<0)break;
x=fa[x][up];
y=fa[y][up];
up--;
}
if(x==y)
return len[xx]+len[yy]-2*len[x]+a[x];
else
return len[xx]+len[yy]-2*len[fa[x][0]]+a[fa[x][0]];
}
vector<long>map[N];
bool ok[N];
void dfs(long now)
{ long i,to,next;
ok[now]=true;
for(i=0;i<map[now].size();i++){
to=map[now][i];
if(!ok[to]){
fa[to][0]=now;
dep[to]=dep[now]+1;
len[to]=a[to]+len[now];
dfs(to);
}
}
}
long ksm(long a,long b)
{
if(b>1)
if(b&1)
return (ll)ksm((ll)a*a%mo,b>>1)*a%mo;
else
return ksm((ll)a*a%mo,b>>1);
else return a;
}
long cha(long x)
{
return (father[x]==x)?x:father[x]=cha(father[x]);
}
void bin(long x,long y)
{
father[cha(x)]=cha(y);
}
int main()
{ long i,xx,yy,r1,r2,r3,r4,w1,w2,w3,w4,maxx;
long long ans=1;
scanf("%ld",&n);
for(i=1;i<=n;i++){
scanf("%ld",&a[i]);
ans=ans*a[i]%mo;
}
out[n]=ans;
for(i=1;i<n;i++){
scanf("%ld%ld",&xx,&yy);
b[i].make(xx,yy);
map[xx].push_back(yy);
map[yy].push_back(xx);
}
dfs(1);
init();
for(i=1;i<n;i++)
scanf("%ld",&c[i]);
for(i=n-1;i>=1;i--){
xx=cha(b[c[i]].x);
yy=cha(b[c[i]].y);
r1=root[cha(xx)].x;
r2=root[cha(xx)].y;
r3=root[cha(yy)].x;
r4=root[cha(yy)].y;
w1=lca(r1,r3);
w2=lca(r1,r4);
w3=lca(r2,r3);
w4=lca(r2,r4);
maxx=max(w1,max(w2,max(w3,max(w4,max(w[xx],w[yy])))));
ans=ans*ksm(w[xx],mo-2)%mo*ksm(w[yy],mo-2)%mo*maxx%mo;
bin(xx,yy);
if(maxx==w1)
root[cha(xx)].make(r1,r3);
if(maxx==w2)
root[cha(xx)].make(r1,r4);
if(maxx==w3)
root[cha(xx)].make(r2,r3);
if(maxx==w4)
root[cha(xx)].make(r2,r4);
if(maxx==w[xx])
root[cha(xx)].make(r1,r2);
if(maxx==w[yy])
root[cha(xx)].make(r3,r4);
w[cha(xx)]=maxx;
out[i]=ans;
}
for(i=1;i<=n;i++)
printf("%ld\n",out[i]);
return 0;
}
JZOJ 5286. 【NOIP2017提高A组模拟8.16】花花的森林 (Standard IO)的更多相关文章
- JZOJ 【NOIP2017提高A组模拟9.14】捕老鼠
JZOJ [NOIP2017提高A组模拟9.14]捕老鼠 题目 Description 为了加快社会主义现代化,建设新农村,农夫约(Farmer Jo)决定给农庄里的仓库灭灭鼠.于是,猫被农夫约派去捕 ...
- [JZOJ 100026] [NOIP2017提高A组模拟7.7] 图 解题报告 (倍增)
题目链接: http://172.16.0.132/senior/#main/show/100026 题目: 有一个$n$个点$n$条边的有向图,每条边为$<i,f(i),w(i)>$,意 ...
- 【NOIP2017提高A组模拟9.7】JZOJ 计数题
[NOIP2017提高A组模拟9.7]JZOJ 计数题 题目 Description Input Output Sample Input 5 2 2 3 4 5 Sample Output 8 6 D ...
- JZOJ 100029. 【NOIP2017提高A组模拟7.8】陪审团
100029. [NOIP2017提高A组模拟7.8]陪审团 Time Limits: 1000 ms Memory Limits: 131072 KB Detailed Limits Got ...
- JZOJ 5328. 【NOIP2017提高A组模拟8.22】世界线
5328. [NOIP2017提高A组模拟8.22]世界线 (File IO): input:worldline.in output:worldline.out Time Limits: 1500 m ...
- JZOJ 5329. 【NOIP2017提高A组模拟8.22】时间机器
5329. [NOIP2017提高A组模拟8.22]时间机器 (File IO): input:machine.in output:machine.out Time Limits: 2000 ms M ...
- JZOJ 5307. 【NOIP2017提高A组模拟8.18】偷窃 (Standard IO)
5307. [NOIP2017提高A组模拟8.18]偷窃 (Standard IO) Time Limits: 1000 ms Memory Limits: 262144 KB Description ...
- JZOJ 5305. 【NOIP2017提高A组模拟8.18】C (Standard IO)
5305. [NOIP2017提高A组模拟8.18]C (Standard IO) Time Limits: 1000 ms Memory Limits: 131072 KB Description ...
- 【NOIP2017提高A组模拟9.17】信仰是为了虚无之人
[NOIP2017提高A组模拟9.17]信仰是为了虚无之人 Description Input Output Sample Input 3 3 0 1 1 7 1 1 6 1 3 2 Sample O ...
随机推荐
- G - Radar Scanner Gym - 102220G(中位数~~)
zThere are n rectangle radar scanners on the ground. The sides of them are all paralleled to the axe ...
- 让mybatis不再难懂(二)
上一篇文章写了mybatis的基本原理和配置文件的基本使用,这一篇写mybatis的使用,主要包括与sping集成.动态sql.还有mapper的xml文件一下复杂配置等.值得注意的是,导图17和18 ...
- C#输入输出及类型转换,变量,常量。
//输出 Console.WriteLine("大哇塞"); 自动回车的. Console.Write("Hello world"); 不带回车的 注意: 1 ...
- 学会使用数据讲故事——Excel研究网络研讨会
编者按:在数据密集型研究的新时代,Excel将成为研究者讲故事的强大工具.在即将举行的Excel研究网络研讨会中,我们将与你探讨如何用新的方式来寻找.查询.分析数据并实现数据可视化.Office 36 ...
- CDC与HDC的区别以及相互转换
CDC是MFC的DC的一个类 HDC是DC的句柄,API中的一个类似指针的数据类型. MFC类的前缀都是C开头的 H开头的大多数是句柄 这是为了助记,是编程读\写代码的好的习惯. CDC中所 ...
- 控制webbrowser滚动到指定位置
在构造函数中添加事件: webBrowser.DocumentCompleted+=new WebBrowserDocumentCompletedEventHandler(webBrowser_Doc ...
- python的IO
格式化输出 格式化输出是指通过print()等函数向指定的地方(比如屏幕)输出指定格式的内容 格式: age = 18 name = "xiaohua" print("我 ...
- R的基础数据结构
- Luogu_1280_尼克的任务
题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成. 尼克的一个工作日为N分钟,从第一分钟开始 ...
- Protocol Buffers学习(4):更多消息类型
介绍一下消息的不同类型和引用 使用复杂消息类型 您可以使用其他消息类型作为字段类型.例如,假设你想在每个SearchResponse消息中包含Result消息,您可以在同一个.proto中定义一个Re ...