6380. 【NOIP2019模拟2019.10.06】小w与最长路(path)
题目
题目大意
给你一棵树,对于每一条边,求删去这条边之后,再用一条边(自己定)连接两个连通块,形成的树的直径最小是多少。
正解
首先,将这棵树的直径给找出来。显然,如果删去的边不在直径上,那么答案就是直径。
接下来考虑删去的边在直径上的情况。
自己连的边应该要是两棵树的直径的中点(中点就是直径上到端点最大距离最小的点)。
答案就是两棵树的直径的一半(当然这是粗略的说法)加上边权,和两棵树内部的直径长度的最大值。
设直径端点为\(S\)和\(T\),现在想象直径是横过来的一条线,有一堆树挂在上面。
在直径上从左到右枚举删去哪条边,顺带着维护中点在哪里。
有个结论:中点肯定在原来的直径上。
(后面都以\(S\)的一边为例,显然另一边是一样的)
反证法,设中点为\(x\),\(x\)不在直径上。设\(y\)为\(x\)到\(S\)路径上第一个出现在直径上的点。
现在找最远的点\(z\)。
如果\(z\)在\(y\)子树之外,那么路径就是\(x\)到\(y\)和\(y\)到\(z\)的距离。这时候如果要使\(y\)到\(z\)最大,则\(z=S\)。这时候将\(x\)变成\(y\)更优。
如果\(z\)在\(x\)子树之内,那么\(x\)到\(z\)的距离比\(x\)到\(S\)的距离长,与假设矛盾。
如果\(z\)在\(y\)子树之内,在\(x\)子树之外,那么\(y\)到\(z\)的距离比\(y\)到\(S\)的距离长,矛盾。
接下来考虑如何维护直径。
在原来的直径上,对于每个节点,预处理出\(f_x\)表示\(x\)子树中最远点到\(x\)的长度。
设\(disS_x\)为\(x\)到\(S\)的距离。
显然,新的直径的一个端点是\(S\)。直径可以分成在原来直径上和在某棵子树内的两段。
设\(x\)为直径的拐点,则直径的长度为\(disS_x+f_x\)
设\(a\)为直径的中点,则直径一半的长度(形象的说法)为\(max(disS_a,disS_x+f_x-disS_a)\)
现在被删去的边在原来的直径上从左往右移动,每个拐点都能搞出一条路径。在这些路径中找长度最大的,作为直径,然后\(a\)移动到\(max(disS_a,disS_x+f_x-disS_a)\)最小的地方,这时候\(a\)就求出来了。
在这个过程中,我们发现\(a\)只会从\(S\)向\(T\)移动。
所以直接\(O(n)\)做就可以了(题解说要单调队列,但实际上完全不用。具体见代码。)
代码
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 2000010
#define ll long long
int n;
struct EDGE{
int to,w,num;
EDGE *las;
} e[N*2],*last[N];
int ne;
unsigned long long num;
unsigned long long get(){
num^=(num<<13);
num^=(num>>17);
num^=(num<<5);
return num;
}
void gen(){
int B,D;
scanf("%d%llu%d%d",&n,&num,&B,&D);
for(int i=2;i<=n;i++){
int a=get()%min(i-1,B)+i-min(i-1,B),b=get()%D;
e[ne]={a,b,i-1,last[i]};
last[i]=e+ne++;
e[ne]={i,b,i-1,last[a]};
last[a]=e+ne++;
}
}
ll ans[N];
int q[N];
ll ds[N],dt[N],alen;
int S,T,pre[N],suc[N];
EDGE *et[N];
void init(){
static int vis[N];
int BZ,h,t;
vis[1]=BZ=1;
q[h=t=1]=1;
ll *dis=ds;
dis[1]=0;
while (h<=t){
int x=q[h++],y;
for (EDGE *ei=last[x];ei;ei=ei->las){
y=ei->to;
if (vis[y]!=BZ){
vis[y]=BZ;
dis[y]=dis[x]+ei->w;
q[++t]=y;
}
}
}
S=1;
for (int i=1;i<=n;++i)
if (dis[i]>dis[S])
S=i;
q[h=t=1]=S;
vis[S]=++BZ;
dis[S]=0;
while (h<=t){
int x=q[h++],y;
for (EDGE *ei=last[x];ei;ei=ei->las){
y=ei->to;
if (vis[y]!=BZ){
vis[y]=BZ;
dis[y]=dis[x]+ei->w;
pre[y]=x;
et[y]=ei;
q[++t]=y;
}
}
}
T=S;
for (int i=1;i<=n;++i)
if (dis[i]>dis[T])
T=i;
for (int i=T;i!=S;i=pre[i])
suc[pre[i]]=i;
suc[T]=0;
for (int i=1;i<=n;++i)
if (!suc[i] && i!=T)
pre[i]=0;
}
ll f[N];
int fa[N];
void dp1(int rt){
int h,t;
q[h=t=1]=rt;
fa[rt]=0;
while (h<=t){
int x=q[h++],y;
for (EDGE *ei=last[x];ei;ei=ei->las){
y=ei->to;
if (y!=pre[rt] && y!=suc[rt] && y!=fa[x]){
ans[ei->num]=alen;
fa[y]=x;
q[++t]=y;
}
}
}
for (int i=t;i>=1;--i){
int x=q[i],y;
f[x]=0;
for (EDGE *ei=last[x];ei;ei=ei->las){
y=ei->to;
if (y!=pre[rt] && y!=suc[rt] && y!=fa[x])
f[x]=max(f[x],f[y]+ei->w);
}
}
}
ll gs[N],gt[N];
void dp2(int rt,int *cant,ll *g){
int h,t;
q[h=t=1]=rt;
fa[rt]=0;
while (h<=t){
int x=q[h++],y;
for (EDGE *ei=last[x];ei;ei=ei->las){
y=ei->to;
if (y!=cant[x] && y!=fa[x]){
fa[y]=x;
q[++t]=y;
}
}
}
for (int i=t;i>=1;--i){
int x=q[i],y;
ll fmx=0,smx=0;
f[x]=0;
g[x]=0;
for (EDGE *ei=last[x];ei;ei=ei->las){
y=ei->to;
if (y!=cant[x] && y!=fa[x]){
g[x]=max(g[x],g[y]);
if (f[y]+ei->w>fmx)
smx=fmx,fmx=f[y]+ei->w;
else if (f[y]+ei->w>smx)
smx=f[y]+ei->w;
}
}
f[x]=fmx;
g[x]=max(g[x],fmx+smx);
}
}
ll hs[N],ht[N];
void calc(int beg,int end,int *nxt,ll *h,ll *dis){
int a=beg,mx=beg;
h[beg]=f[beg];
for (int x=nxt[beg];x!=end;x=nxt[x]){
if (dis[x]+f[x]>dis[mx]+f[mx]){
mx=x;
while (a!=x && max(dis[nxt[a]],dis[mx]+f[mx]-dis[nxt[a]])<max(dis[a],dis[mx]+f[mx]-dis[a]))
a=nxt[a];
}
h[x]=max(dis[a],dis[mx]+f[mx]-dis[a]);
}
}
int main(){
freopen("path.in","r",stdin);
freopen("path.out","w",stdout);
gen();
init();
alen=ds[T];
dp2(T,suc,gs),dp2(S,pre,gt);
for (int i=S;i;i=suc[i])
dt[i]=alen-ds[i],dp1(i);
calc(S,T,suc,hs,ds);
calc(T,S,pre,ht,dt);
for (int i=S;i!=T;i=suc[i])
ans[et[suc[i]]->num]=max(max(gs[i],gt[suc[i]]),hs[i]+ht[suc[i]]+et[suc[i]]->w);
ll s=0;
for (int i=1;i<n;++i)
s^=ans[i]%998244353*i%998244353;
printf("%lld\n",s);
return 0;
}
总结
论猜结论的重要性……
6380. 【NOIP2019模拟2019.10.06】小w与最长路(path)的更多相关文章
- 6389. 【NOIP2019模拟2019.10.26】小w学图论
题目描述 题解 之前做过一次 假设图建好了,设g[i]表示i->j(i<j)的个数 那么ans=∏(n-g[i]),因为连出去的必定会构成一个完全图,颜色互不相同 从n~1染色,点i的方案 ...
- 【NOIP2019模拟2019.10.07】果实摘取 (约瑟夫环、Mobius反演、类欧、Stern-Brocot Tree)
Description: 小 D 的家门口有一片果树林,果树上果实成熟了,小 D 想要摘下它们. 为了便于描述问题,我们假设小 D 的家在二维平面上的 (0, 0) 点,所有坐标范围的绝对值不超过 N ...
- 6392. 【NOIP2019模拟2019.10.26】僵尸
题目描述 题解 吼题但题解怎么这么迷 考虑一种和题解不同的做法(理解) 先把僵尸离散化,h相同的钦(ying)点一个大小 (可以发现这样每种情况只会被算正好一次) 计算完全被占领的方案,然后1-方案/ ...
- 6377. 【NOIP2019模拟2019.10.05】幽曲[埋骨于弘川]
题目描述 题解 随便bb 详细题解见 https://www.cnblogs.com/coldchair/p/11624979.html https://blog.csdn.net/alan_cty/ ...
- 6383. 【NOIP2019模拟2019.10.07】果实摘取
题目 题目大意 给你一个由整点组成的矩形,坐标绝对值范围小于等于\(n\),你在\((0,0)\),一开始面向\((1,0)\),每次转到后面第\(k\)个你能看到的点,然后将这条线上的点全部标记删除 ...
- 6374. 【NOIP2019模拟2019.10.04】结界[生与死的境界]
题目 题目大意 给你一个数列,每次可以选择任意两个相邻的数\(x\)和\(y\),将其删去,并在原来位置插入\(x+2y\). 每次询问一个区间,对这个区间进行上述操作.求最后剩下的数最大是多少. 答 ...
- 【NOIP2017模拟6.25】小W的动漫
题目 小W最近迷上了日本动漫,每天都有无数部动漫的更新等着他去看,所以他必须将所有的动漫排个顺序,当然,虽然有无数部动漫,但除了1号动漫,每部动漫都有且仅有一部动漫是它的前传(父亲),也就是说,所有的 ...
- 洛谷P5284 [十二省联考2019]字符串问题(SAM+倍增+最长路)
题面 传送门 题解 首先,我们把串反过来,那么前缀就变成后缀,建一个\(SAM\).我们发现一个节点的后缀是它的所有祖先 那么我们是不是直接按着\(parent\)树建边就可以了呢? 显然不是.我们假 ...
- [JZOJ6359] 【NOIP2019模拟2019.9.15】小ω的树
题目 题目大意 给你一棵树,带点权和边权. 要你选择一个联通子图,使得点权和乘最小边权最大. 支持修改点权操作. 思考历程 显然,最先想到的当然是重构树了-- 重构树就是在做最大生成树的时候,当两个联 ...
随机推荐
- Day One-Python基础
Python第一节 安装教程就不发了,太心累了!大家可以上百度查,网上都会有 python种类 JavaPython cPython pypy 两种编码 字节码 和 机器码 unicode utf8 ...
- 企业实践 | 如何更好地使用 Apache Flink 解决数据计算问题?
业务数据的指数级扩张,数据处理的速度可不能跟不上业务发展的步伐.基于 Flink 的数据平台构建.运用 Flink 解决业务场景中的具体问题等随着 Flink 被更广泛的应用于广告.金融风控.实时 B ...
- delphi 随意将函数执行权限提高到Ring0源代码
//随意将函数执行权限提高到Ring0源代码//Windows 2K以上的操作系统,//用途: 提供超级简单使用的APIrocessRing0(),//可将delphi中的任意函数由原來的Ring3权 ...
- AcWing 207. 球形空间产生器 (高斯消元)打卡
有一个球形空间产生器能够在n维空间中产生一个坚硬的球体. 现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器. ...
- thinkcmf5 pc切换手机
1.在simplewind\cmf\common.php 里找到“获取当前主题名”添加 if(cmf_is_mobile()){ $theme = config('cmf_mobile_default ...
- Java核心基础知识(一):概念、语法、使用、源码
1. Java中OOP的特点? OOP(Object Oriented Programming):面向对象编程.具有封装.继承.多态三大特征. 封装:解决数据安全性问题: 继承:解决代码的重用性问题: ...
- 用scp实现多服务器文件分发
需要安装expect环境 yum install expect -y vi ip.txt #主机地址池 192.168.1.1 192.168.1.2 192.168.3.3 #如果是同一网段也可以不 ...
- Codeforces Round #499 (Div. 2) Problem-A-Stages(水题纠错)
CF链接 http://codeforces.com/contest/1011/problem/A Natasha is going to fly to Mars. She needs to bui ...
- 5.如何使用jmeter参数话
参数化:简单的来理解一下,我们录制了一个脚本,这个脚本中有登录操作,需要输入用户名和密码,假如系统不允许相同的用户名和密码同时登录,或者更好的模拟多个用户来登录系统.这个时候就需要对用户名和密码进行参 ...
- JPA的入门CRUD
主要目的: 操作实体类就相当于操作数据库表 建立两个映射关系: 实体类和表的映射关系 实体类中的属性和表中字段的映射关系 不在关注sql语句 常见的orm框架:Mybatis(ibatis).Hibe ...