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)的更多相关文章

  1. JZOJ 【NOIP2017提高A组模拟9.14】捕老鼠

    JZOJ [NOIP2017提高A组模拟9.14]捕老鼠 题目 Description 为了加快社会主义现代化,建设新农村,农夫约(Farmer Jo)决定给农庄里的仓库灭灭鼠.于是,猫被农夫约派去捕 ...

  2. [JZOJ 100026] [NOIP2017提高A组模拟7.7] 图 解题报告 (倍增)

    题目链接: http://172.16.0.132/senior/#main/show/100026 题目: 有一个$n$个点$n$条边的有向图,每条边为$<i,f(i),w(i)>$,意 ...

  3. 【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 ...

  4. JZOJ 100029. 【NOIP2017提高A组模拟7.8】陪审团

    100029. [NOIP2017提高A组模拟7.8]陪审团 Time Limits: 1000 ms  Memory Limits: 131072 KB  Detailed Limits   Got ...

  5. JZOJ 5328. 【NOIP2017提高A组模拟8.22】世界线

    5328. [NOIP2017提高A组模拟8.22]世界线 (File IO): input:worldline.in output:worldline.out Time Limits: 1500 m ...

  6. JZOJ 5329. 【NOIP2017提高A组模拟8.22】时间机器

    5329. [NOIP2017提高A组模拟8.22]时间机器 (File IO): input:machine.in output:machine.out Time Limits: 2000 ms M ...

  7. JZOJ 5307. 【NOIP2017提高A组模拟8.18】偷窃 (Standard IO)

    5307. [NOIP2017提高A组模拟8.18]偷窃 (Standard IO) Time Limits: 1000 ms Memory Limits: 262144 KB Description ...

  8. 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 ...

  9. 【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 ...

随机推荐

  1. java高并发之线程池

    Java高并发之线程池详解   线程池优势 在业务场景中, 如果一个对象创建销毁开销比较大, 那么此时建议池化对象进行管理. 例如线程, jdbc连接等等, 在高并发场景中, 如果可以复用之前销毁的对 ...

  2. OfficeCommandbarDesigner20170202.rar

    OfficeCommandbarDesigner用于对Office各个常用组件.VBE的工具栏进行查看和编辑的工具. 界面主要分为上下两个表格控件,上面的控件列举出所有Commandbar,下面的控件 ...

  3. [LC] 61. Rotate List

    Given a linked list, rotate the list to the right by k places, where k is non-negative. Example 1: I ...

  4. 总结verilog产生随机数的$random和seed

      $random(seed)是verilog中最简单的产生随机数的系统函数. 在调用系统函数$random(seed)时,可以写成三种样式:1)$random,2)$random(),3)$rand ...

  5. leetcode第23题:合并K个排序链表

    首先我想到的是采用一般递归法,将K个链表合并化为(k-1)两个链表合并 class Solution: def mergeKLists(self, lists: List[ListNode]) -&g ...

  6. LG_2869_[USACO07DEC]美食的食草动物Gourmet Grazers

    题目描述 Like so many others, the cows have developed very haughty tastes and will no longer graze on ju ...

  7. excel中ppmt/pmt/ipmt的计算方式

    参考来源: https://www.experts-exchange.com/articles/1948/A-Guide-to-the-PMT-FV-IPMT-and-PPMT-Functions.h ...

  8. Docker For Mac 下安装 Rancher

    https://www.jianshu.com/p/5fb3e1a998d6 Docker For Mac 下安装 Rancher 原文:如何在 OS X 上安装 Rancher Rancher 是 ...

  9. python对csv读写

    1.csv文件读取 with open("C:\\Users\\Administrator\\Desktop\\test.csv", 'r', encoding='utf-8') ...

  10. 阿里云ECS 实例Centos7系统磁盘扩容

    需求:一台阿里云的数据盘磁盘空间不足,需要扩容,我这里只有一个主分区,ext4文件系统. 因为磁盘扩容场景不同,阿里云的文档比较全面一些,所以先奉上阿里云的文档,下面开始我的操作步骤: 1.登录控制台 ...