【JZOJ4899】【NOIP2016提高A组集训第17场11.16】雪之国度
题目描述
雪之国度有N座城市,依次编号为1到N,又有M条道路连接了其中的城市,每一条道路都连接了不同的2个城市,任何两座不同的城市之间可能不止一条道路。雪之女王赋予了每一座城市不同的能量,其中第i座城市被赋予的能量为Wi。
如果城市u和v之间有一条道路,那么只要此刻雪之女王的能量不小于|Wu-Wv|,这条道路就是安全的。如果城市u和v之间存在两条没有重复道路的安全路径(其中每一段道路都是安全的),则认为这两座城市之间有着良好的贸易关系。
最近,雪之女王因为情感问题,她的能量产生巨大的波动。为了维持雪之国度的经济贸易,她希望你能帮忙对Q对城市进行调查。对于第j对城市uj和vj,她希望知道在保证这两座城市之间有着良好贸易关系的前提之下,自己最少需要保持多少的能量。
数据范围
对于20%的数据来说,3<=N<=10, 3<=M<=20, 1<=Q<=10
对于另30%的数据来说,Wi=0
对于100%的数据来说,3<=N<=100000, 3<=M<=500000, 1<=Q<=100000, 每一座城市的能量Wi满足0<=Wi<=200000.
=w=
对原树进行最小生成树,一开始所有树边,对剩余的边按权值从小到大进行操作:
对于一条(u,v,w)的边,在最小生成树上(u,v)的这条路径上的所有标记为未修改的边权改为w,并把它们标记为已修改。
所有边都加入了以后,对于每个询问(u,v),都使用LCA求树上路径的最大值即可。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define sqr(x) ((x)*(x))
#define ln(x,y) int(log(x)/log(y))
using namespace std;
const char* fin="tour.in";
const char* fout="tour.out";
const int inf=0x7fffffff;
const int maxn=100009,maxm=maxn*2,maxk=17;
int n,m,q,i,j,k;
int a[maxn],b[maxn];
int fi[maxn],la[maxm],ne[maxm],tot;
int fa[maxn][maxk],de[maxn];
void add_line(int a,int b){
tot++;
ne[tot]=fi[a];
la[tot]=b;
fi[a]=tot;
}
void pre(int v,int from){
int i,j,k;
de[v]=de[from]+1;
for (i=1;i<maxk;i++) fa[v][i]=fa[fa[v][i-1]][i-1];
for (k=fi[v];k;k=ne[k])
if (la[k]!=from){
fa[la[k]][0]=v;
pre(la[k],v);
}
}
void up(int &a,const int &i,int &ans){
ans+=1<<i;
a=fa[a][i];
}
int lca(int a,int b){
int i,j,k=0;
if (de[a]<de[b]) swap(a,b);
for (i=maxk-1;i>=0;i--) if (de[fa[a][i]]>de[b]) up(a,i,k);
if (de[a]!=de[b]) up(a,0,k);
for (i=maxk-1;i>=0;i--) if (fa[a][i]!=fa[b][i]) up(a,i,k),up(b,i,k);
if (a!=b) up(a,0,k),up(b,0,k);
return k;
}
struct path{
int x,y,len;
void init(){
x=y=len=0;
}
path(){
init();
}
void get(const int &X,const int &Y,const int &Len){
if (Len>len){
x=X;
y=Y;
len=Len;
}
}
void update(int A,int B);
}li[maxn],Old,Ans,New;
void path::update(int A,int B){
if (A==0 || B==0) return;
int i=lca(A,B);
if (a[A]!=a[B]) Ans.get(A,B,i);
if (i>len) get(A,B,i);
}
path merge(const path &a,const path &b){
path c;
if (a.x==0) return b;
if (b.x==0) return a;
if (a.len>b.len) c.get(a.x,a.y,a.len);
else c.get(b.x,b.y,b.len);
c.update(a.x,b.x);
c.update(a.x,b.y);
c.update(a.y,b.x);
c.update(a.y,b.y);
return c;
}
void dfs(int v,int from){
int i,j,k,co=a[v];
New.init();
New.x=New.y=v;
li[co]=merge(li[co],New);
for (k=fi[v];k;k=ne[k])
if (la[k]!=from) dfs(la[k],v);
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d%d%d",&n,&m,&q);
for (i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for (i=1;i<n;i++){
scanf("%d%d",&j,&k);
add_line(j,k);
add_line(k,j);
}
pre(1,0);
dfs(1,0);
for (i=1;i<=q;i++){
scanf("%d",&j);
Old.init();
Ans.init();
b[0]=0;
for (;j;j--){
scanf("%d",&b[++b[0]]);
Old=merge(Old,li[b[b[0]]]);
}
Ans.len++;
if (Ans.len==1) printf("-1\n");
else printf("%d\n",Ans.len);
}
return 0;
}
=o=
我认为这一道题最难点在于想出:最小生成树。
我在比赛时做这一道题,想着对于每一个询问,二分答案后使用边双来判断答案是否合法。
但是这个时间复杂度会是O(q∗log∗n)。
一直想要使用交集优化来优化时间,但是,无法优化。
然后我就懵逼了。
如果我们按顺序加入一些边的话,那么我们就可以保证,加入边之后的答案会最优化。
所以就能得出使用最小生成树这个思路。
【JZOJ4899】【NOIP2016提高A组集训第17场11.16】雪之国度的更多相关文章
- 【JZOJ4898】【NOIP2016提高A组集训第17场11.16】人生的价值
题目描述 NiroBC终于找到了人生的意义,可是她已经老了,在新世界,没有人认识她,她孤独地在病榻上回顾着自己平凡的一生,老泪纵横.NiroBC多么渴望再多活一会儿啊! 突然一个戴着黑色方框眼镜,方脸 ...
- 【JZOJ4901】【NOIP2016提高A组集训第18场11.17】矩阵
题目描述 他是一名普通的农电工,他以一颗无私奉献的爱岗敬业之心,刻苦钻研业务,以娴熟的技术.热情周到的服务赢得了广大客户的尊敬和赞美.他就是老百姓称为"李电"的李春来. 众所周知, ...
- 【NOIP2016提高A组集训第4场11.1】平衡的子集
题目 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 分析 如果暴力枚举每个人被分到哪 ...
- 【JZOJ4855】【NOIP2016提高A组集训第6场11.3】荷花池塘
题目描述 于大夫建造了一个美丽的池塘,用来让自己愉快的玩耍.这个长方形的池子被分割成了M 行 和N 列的正方形格子.池塘中有些地方是可以跳上的荷叶,有些地方是不能放置荷叶也不 能跳上的岩石,其他地方是 ...
- 【JZOJ4841】【NOIP2016提高A组集训第4场11.1】平衡的子集
题目描述 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 数据范围 40%的数据满足: ...
- 【NOIP2016提高A组集训第14场11.12】随机游走
题目 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己是不 ...
- 【NOIP2016提高A组集训第13场11.11】最大匹配
题目 mhy12345学习了二分图匹配,二分图是一种特殊的图,其中的点可以分到两个集合中,使得相同的集合中的点两两没有连边. 图的"匹配"是指这个图的一个边集,里面的边两两不存在公 ...
- 【NOIP2016提高A组集训第14场11.12】随机游走——期望+树形DP
好久没有写过题解了--现在感觉以前的题解弱爆了,还有这么多访问量-- 没有考虑别人的感受,没有放描述.代码,题解也写得歪歪扭扭. 并且我要强烈谴责某些写题解的代码不打注释的人,像天书那样,不是写给普通 ...
- 【JZOJ4893】【NOIP2016提高A组集训第15场11.14】过河
题目描述 数据范围 解法 由于同一个点,同一个圆盘最多只会走一次. 把(i,j)当作一个点,表示第i个点,放第i个圆盘. 那么就可以使用最短路. 时间复杂度为O(n4∗k). 事实上存在冗余圆盘,一个 ...
随机推荐
- 转载 ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(三) 激动人心的时刻到啦,实现1v1聊天
ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(三) 激动人心的时刻到啦,实现1v1聊天 看起来挺简单,细节还是很多的,好,接上一篇,我们已经成功连接singalR服务器 ...
- MyBatis配置文件(二)--settings配置
settings是MyBatis中最复杂的配置,它能影响MyBatis底层的运行,大部分情况下使用默认值,只需要修改一些常用的规则即可.常用规则有自动映射.驼峰命名映射.级联规则.是否启动缓存.执行器 ...
- 2019牛客暑期多校赛(第一场) A Equivalent Prefixes(单调栈)
传送门:https://ac.nowcoder.com/acm/contest/881/A 题意:给定两个数组a和b,求最大的p,满足在区间 [1,p] 中任何区间的两个数组的最小值的下标都相等. 思 ...
- org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]
从hibernate3升级到4应该会遇到 应该添加引用 <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 ...
- 2018-2-13-visual-Studio-无法调试,提示程序跟踪已退出
title author date CreateTime categories visual Studio 无法调试,提示程序跟踪已退出 lindexi 2018-2-13 17:23:3 +0800 ...
- 查看linux系统的文件inode号码使用情况
:~$ df -i 文件系统 Inode 已用(I) 可用(I) 已用(I)% 挂载点 udev % /dev tmpfs % /run /dev/sda2 % / tmpfs % /dev/shm ...
- 通过游戏学python 3.6 第一季 第四章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释 可复制直接使用 娱乐 可封装 函数
#猜数字--核心代码--猜测次数--随机函数和屏蔽错误代码---优化代码及注释 #!usr/bin/env python #-*-coding:utf-8-*- #QQ124111294 import ...
- ES6学习笔记之块级作用域
ES6学习笔记:块级作用域 作用域分类 全局作用域 局部作用域 块级作用域 全局作用域示例 var i=2; for (var i = 0; i < 10; i++) { } console.l ...
- python 升级后正确安装 pip
由于服务器的python 版本是2.6.6 , 为了使用 twisted 升级至 2.7.13 , 如果此时直接用 yum install python-pip 安装 pip, 则实际pip 会安装在 ...
- python 发送邮件短信封装
发送邮件 需要开启163的smtp服务 import smtplib from email.mime.text import MIMEText class MailSender(): def __in ...