题目描述

“特大新闻,特大新闻!全国爆发了一种极其可怕的病毒,已经开始在各个城市 中传播开来!全国陷入了巨大的危机!大量居民陷入恐慌,想要逃到其它城市以 避难!经调查显示,该病毒来自于C 市的A 学校的一次非法的……” “哎。”你关上电视,叹了口气。作为A 学校的校长,你一天前为了保命,独自 逃离了A 学校,抛弃了全校师生,包括那个曾经帮你计算并拆除道路的工程师。 你良心受到了巨大的谴责,因此决定做出一些补救,回答一些逃难的人提出的询 问。 已知该国一共有n 个城市,并且1 号城市是首都。(n-1)条双向的公路连接这些 城市,通过这些公路,任意两个城市之间存在且仅存在一条路径。每条公路有一 个长度。如果一个城市只与一条公路相连,则称它为边境城市。 该国政府有一个奇怪的规定:每个城市有一个封闭系数di,定义di 为离这个城 市最远的边境城市到这个城市的距离。市民们认为,一个城市的安全系数Si 和 它的封闭系数有很重要的联系。a,b,c 是该国的幸运数字,所以大家公认一个 城市的安全系数Si = (di + a) * b mod c。 市民们一共会提出m 次询问。每个询问包含三个信息,xi,yi 和qi。xi 是询问 者所在的城市编号。你要为这个询问者在xi 到yi 的必经之路上找出一个离xi 最近的避难城市,并且要求这个避难城市的安全系数大于等于qi。如果存在这 样的城市(包含xi 和yi),则输出城市编号,否则输出一行包括一个数-1。

输入

第一行五个数:依次是n, m, a, b, c。 接下来n-1 行描述公路的信息。每行三个数,前两个数代表这条公路连接的两个 城市的编号,第三个数表示这条公路的长度。 再接下来m 行,每行描述一个询问,包含三个数xi, yi 和qi。

输出

对于每个询问,输出一行包含一个整数,存在符合要求的城市则输出城市编号, 不存在则输出-1。

样例输入

7 6 5 6 20

1 2 4

2 4 2

2 5 3

1 3 5

3 6 6

6 7 7

7 5 15

3 4 5

5 4 2

4 5 2

6 6 10

3 5 19

样例输出

6

3

2

4

6

-1

这个题目本身就是两种题型的合并

1、树的最长路径

2、树形倍增数组寻找最值

m^2p 刚学倍增就做这种有(wei)趣(suo)的题真的好吗

先解决最长链的问题,我用的是DP做法,时间复杂度为O(n):

设g[root][0]与g[root][1]为以root为根节点的子树由树根到叶节点的最长链和次长链,注意,最长链与次长链无重合边

一次DFS即可初始化

再设f[root][0]与f[root][1]表示以root为起点的最长链和次长链,也无重合边,一次DFS也可做到

最麻烦的就是倍增查询了:

先看看m的范围 300000

300000 是一个转折点,因为O(nlognlogn)在300000下会TLE

这就让我们只能用O(nlogn)来解决问题

状态应该不难定义:

设f[i][j]表示i节点的第2j个祖先的节点编号

设g[i][j]表示i节点到第2j个祖先之间的点权最大值

接下来便是O(logn)的查询,O(longnlogn)很好想,但现实就是这么骨感QwQ

设c=LCA(a,b),将一个路径拆分成a−>c−>b两部分

将总任务拆分成两个子任务

将一条x−y的直链看成A和B两部分

A中包含2的整数次幂个节点,且A的长度大于x−y总长度的一半

通过这样的观点来考察上述两个子任务:

一、离x最近的:

知道k时,可以O(1)判断答案是否在A中。

① 如果在A中,枚举i从k−1到0即可得到答案。

② 如果A中不存在合法解,则令x=f[x][k],递归进行以上过程。

对于①,整个递归过程中只有得出答案前会被执行一次。

对于②,每次递归后k的值减少,而k上界为logn,下界为0,所以递归深度为O(logn)

综上,该操作复杂度为O(logn)

二、离x最远的:

① 优先令x=f[x][k],递归在B段中求解。如递归返回后已经得到答案,则直接返回答案。

② 如经过①没有获得答案,则O(1)检查A段中是否有答案,如果没有,则x−y整段路径中无解。如果有,则枚举i从k−1到0即可定位答案。

类似子任务一,该部分的复杂度为O(logn)。

码了三个小时,终于AC了!!!!!!

代码如下:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm> #define LOG 20
#define maxn 100000 using namespace std; inline int getint()
{
int num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
} int s[maxn+5];
int fir[2*maxn+5],nxt[2*maxn+5],to[2*maxn+5],dis[2*maxn+5],cnt;
int n,m,a,b,c; inline void newnote(int u,int v,int w){to[++cnt]=v,dis[cnt]=w,nxt[cnt]=fir[u],fir[u]=cnt;} struct node1{ int f[maxn+5][2],g[maxn+5][2];
bool vis[maxn+5]; inline void work(int root)
{
int i;
vis[root]=1;
for(i=fir[root];i;i=nxt[i]) if(!vis[to[i]])
{
work(to[i]);
if(g[to[i]][0]+dis[i]>g[root][0])
g[root][1]=g[root][0],g[root][0]=g[to[i]][0]+dis[i];
else if(g[to[i]][0]+dis[i]>g[root][1])
g[root][1]=g[to[i]][0]+dis[i];
}
} inline void dp(int x,int fa,int c)
{
vis[x]=1;
if(x==1)
f[x][0]=g[x][0],f[x][1]=g[x][1];
else if(f[fa][0]==g[x][0]+c)
{
if(g[x][0]>=f[fa][1]+c)
f[x][0]=g[x][0],f[x][1]=max(f[fa][1]+c,g[x][1]);
else
f[x][0]=f[fa][1]+c,f[x][1]=g[x][0];
}
else
f[x][0]=f[fa][0]+c,f[x][1]=g[x][0];
for(int i=fir[x];i;i=nxt[i])
if(!vis[to[i]])dp(to[i],x,dis[i]);
} }farthest; struct node2{ int f[maxn+5][LOG+1],g[maxn+5][LOG+1],dep[maxn+5];
bool vis[maxn+5]; inline void dfs(int x)
{
for(int i=fir[x];i;i=nxt[i]) if(!vis[to[i]])
{
vis[to[i]]=1;dep[to[i]]=dep[x]+1;f[to[i]][0]=x;
g[to[i]][0]=max(s[to[i]],s[x]);dfs(to[i]);
}
} inline void dp()
{
for(int j=1;j<=LOG;j++)for(int i=1;i<=n;i++)
{
f[i][j]=f[f[i][j-1]][j-1];
g[i][j]=max(g[f[i][j-1]][j-1],g[i][j-1]);
}
} inline int getg(int u,int k)
{
int ans=-(1<<30);
for(int i=LOG;i>=0;i--)
if(k&(1<<i))ans=max(ans,g[u][i]),u=f[u][i];
return ans;
} inline int getk(int u,int k)
{
for(int i=LOG;i>=0;i--)
if(k&(1<<i))u=f[u][i];
return u;
} inline int getd(int u,int d){return getk(u,dep[u]-d);} inline int LCA(int u,int v)
{
int x=getd(u,min(dep[v],dep[u]));
int y=getd(v,min(dep[u],dep[v]));
if(x==y)return x;
for(int i=LOG;i>=0;i--)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[x][0];
} inline int getg1(int x,int y,int w)
{
if(x==y)return s[x]>=w?x:-1;
int t=log2(dep[x]-dep[y]);
if(g[x][t]>=w)
{
for(int i=t-1;i>=0;i--)
if(g[x][i]<w)x=f[x][i];
return s[x]>=w?x:f[x][0];
}
else return getg1(f[x][t],y,w);
} inline int getg2(int x,int y,int w)
{
if(x==y)return s[x]>=w?x:-1;
int t=log2(dep[x]-dep[y]);
int tmp=getg2(f[x][t],y,w);
if(tmp!=-1) return tmp;
if(g[x][t]>=w)
{
for(int i=t-1;i>=0;i--)
if(g[f[x][i]][i]>=w)x=f[x][i];
return s[f[x][0]]>=w?f[x][0]:x;
}
return -1;
} }getans; int main()
{
int i,u,v,w;
n=getint(),m=getint(),a=getint(),b=getint(),c=getint();
for(i=1;i<n;i++)
{
u=getint(),v=getint(),w=getint();
newnote(u,v,w),newnote(v,u,w);
}
farthest.work(1);
memset(farthest.vis,0,sizeof farthest.vis);
farthest.dp(1,0,0);
for(i=1;i<=n;i++)
s[i]=((long long)((farthest.f[i][0]+a)%c)*(b%c))%c;
getans.dep[1]=getans.vis[1]=1,getans.dfs(1);
getans.dp();
for(i=1;i<=m;i++)
{
u=getint(),v=getint(),w=getint();
if(u==v){printf("%d\n",s[u]<w?-1:u);continue;}
int lca=getans.LCA(u,v);
int g1=getans.getg1(u,lca,w),g2=getans.getg2(v,lca,w);
if(~g1)printf("%d\n",g1);
else printf("%d\n",g2);
}
}

CQBZOJ 【重庆市NOIP模拟赛】避难向导的更多相关文章

  1. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  2. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  3. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  4. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  5. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  6. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  7. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  8. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  9. CH Round #52 - Thinking Bear #1 (NOIP模拟赛)

    A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...

随机推荐

  1. 文本框(代替input)输入长度限制、提示

    <div class="inform_content_text"> <textarea name="name" placeholder=&qu ...

  2. 两种常见的缓存淘汰算法LFU&LRU

    1. LFU 1.1. 原理 LFU(Least Frequently Used)算法根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”. 1.2.  ...

  3. 学习Java第七周

    重要知识点 1.“super”的用法 构造器和方法,都用关键字super指向超类,但是用的方法不一样.方法用这个关键字去执行被重载的超类中的方法 2.接口和抽象类的异同 相同: 1.接口和抽象类都有抽 ...

  4. ELK学习实验010:Logstash简介

    Logstash是具有实时流水线功能的开源数据收集引擎.Logstash可以动态统一来自不同来源的数据,并将数据规范化为您选择的目标.清除所有数据并使其民主化,以用于各种高级下游分析和可视化用例. 虽 ...

  5. Linux系统下 docker安装命令

    centos sudo: 使用 root 权限登录 Centos.确保 yum 包更新到最新.yum update 卸载旧版本(如果安装过旧版本的话)yum remove docker docker- ...

  6. POJ1144 Network 题解 点双连通分量(求割点数量)

    题目链接:http://poj.org/problem?id=1144 题目大意:给以一个无向图,求割点数量. 这道题目的输入和我们一般见到的不太一样. 它首先输入 \(N\)(\(\lt 100\) ...

  7. React useEffect的源码解读

    前言 对源码的解读有利于搞清楚Hooks到底做了什么,如果您觉得useEffect很"魔法",这篇文章也许对您有些帮助. 本篇博客篇幅有限,只看useEffect,力求简单明了,带 ...

  8. 小小知识点(四十八)——发送端已知CSI,基于预编码技术,进一步提高MIMO系统和用户的吞吐量

    1.预编码技术的概念 对于空间复用,LTE既支持开环方式的空间复用(发端未知CSI),也支持闭环方式的空间复用(发端已知CSI) 对于LTE中闭环方式的空间复用(即预编码系统)中,发射机可以根据信道条 ...

  9. realme X2谷歌套件

    目前市面上的很多手机是不支持谷歌相关组件的,经过不断的测试成功适配realme X2(真机测试完美适配) 为框架的GMS是用户想要体验整套Google服务不可绕开的一环,Google地图.Play商店 ...

  10. spring boot集成spring-boot-starter-mail邮件功能

    前情提要 以目前IT系统功能来看,邮件功能是非常重要的一个功能.例如:找回密码.邮箱验证,邮件动态码.忘记密码,邮件营销等,都需要用到邮件功能.结合当下最流行的spring boot微服务,推出了sp ...