当前位置: 首页 > news >正文

图论好题推荐-逛公园

题目

在这里插入图片描述
在这里插入图片描述

题解

前置知识

学会使用 tarjan 算法找环,会使用树上倍增求两点间路径的编号最大值与最小值。

思路

pip_{i}piiii 作为题目中的 lll ,可以匹配到的最大 rrr 。因为 rrr 越大,包含的边和点就越多,所以 [i,i],[i,i+1],[i,pi−1],[i,pi][i,i],[i,i+1],[i,p_{i} -1],[i,p_{i} ][i,i],[i,i+1],[i,pi1],[i,pi] 作为 [l,r][l,r][l,r] 都是可以满足题意的。
下面考虑两个问题:

  1. 如何求 pip_{i}pi
  2. 如何利用 pip_{i}pi 求解答案?
如何求 $p_{i} $?

首先找环,可以遍历一棵 DFS 搜索树,如果出现返租边,就是出现了环。
对于每个环,求出环中点的编号的最大值(记为 max1max1max1)与最小值(记为 min1min1min1)。因为每次出现环是在出现返祖边的时候,所以求一下这条返祖边所连接的两个点之间路径上的点中的编号的最大值和最小值即可,可以用倍增优化,logloglog 级别。显然,如果某个区间 [l,r][l,r][l,r] 同时包含这个环的 min1min1min1max1max1max1,则该区间 [l,r][l,r][l,r] 一定不合法,反之,该区间 [l,r][l,r][l,r] 不会在这个环中不合法。
记 $pos_{i} $ 为 iii 作为环中编号最小点时,其对应的环中的编号最大点的编号最小值。因为同一个点有可能存在于多个环中(如图一),并且有可能在这些环中都是编号最小的点,所以要取对应的编号最大点的编号最小值。
这里的用处以后会知道。

图一。题目中只保证不存在一条边同时存在于两个不同的简单环,但可能有一个点在多个环中。

每次找到环时,posmin1=min(posmin1,max1)pos_{min1}=min(pos_{min1},max1)posmin1=min(posmin1,max1) 更新即可。
pip_{i}pi,考虑 j(i≤j≤n)j(i\le j\le n)j(ijn),jjj 带给 $p_{i} $ 的限制就是:$p_{i} < pos_{j} $,因为如果 $p_{i} $ 取到 posjpos_{j}posj 或者更大,就会同时包含 jjjposjpos_{j}posj,不合法。那么显然 pi=min⁡(posj−1)p_{i}=\min (pos_{j}-1)pi=min(posj1),求一个后缀最小值即可。

图二。结合样例理解 pospospos 数组和 ppp 数组含义(INF表示没有)。

编号12345678
pos3INFINF8INFINFINFINF
p27778888
如何利用 pip_{i}pi 求解答案?

可以暴力枚举 jjjxxxyyy,答案即为 ∑j=xy(min(y,pj)−j+1)\sum_{j=x}^{y}(min(y,p_{j})-j+1)j=xy(min(y,pj)j+1),时间复杂度O(nq)O(nq)O(nq)
考虑优化,显然可以看出,ppp 数组是单调不降的,故可以二分出在 xxxyyy 之间第一个p[]≥yp[ ]\ge yp[]y 的点,下标记为 kkk。对于任意 j(k≤j≤)j(k \le j \le )j(kj),有 y≤pjy\le p_{j}ypj,故 min(y,pj)=ymin(y,p_{j})=ymin(y,pj)=y,其贡献为 ∑j=ky(y−j+1)\sum_{j=k}^{y} (y-j+1)j=ky(yj+1),整理得 ∑j=ky(−j+1)+∑j=kyy\sum_{j=k}^{y} (-j+1)+\sum_{j=k}^{y} yj=ky(j+1)+j=kyy,可O(1)O(1)O(1)求出。
对于任意 KaTeX parse error: Undefined control sequence: \lej at position 4: j(x\̲l̲e̲j̲<k),有 min(y,pj)=pjmin(y,p_{j})=p_{j}min(y,pj)=pj。故其贡献为 ∑j=xk−1(pj−j+1)\sum_{j=x}^{k-1}(p_{j}-j+1)j=xk1(pjj+1),整理得 ∑j=xk−1pj+∑j=xk−1(−j+1)\sum_{j=x}^{k-1}p_{j}+\sum_{j=x}^{k-1}(-j+1)j=xk1pj+j=xk1(j+1),预处理前缀和,也可 O(1)O(1)O(1) 求出。
求解答案的总复杂度为 O(qlog⁡2n)O(q\log_{2}{n})O(qlog2n)

代码

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7,N=3e5+5;
bool_priority birdtjg=1;
int n,m,q;
vector<int> a[N];
int p[N],dfn[N],fmin_[N][30],fmax_[N][30],to[N][30],pos[N];
long long sp[N];      //注意开long long!
void dfs(int x,int fa)
{dfn[x]=dfn[fa]+1;  //dfn为深度fmin_[x][0]=min(fa,x),fmax_[x][0]=max(fa,x);to[x][0]=fa;for(int i=1;i<=20;i++) //倍增优化{to[x][i]=to[to[x][i-1]][i-1];fmin_[x][i]=min(fmin_[x][i-1],fmin_[to[x][i-1]][i-1]);fmax_[x][i]=max(fmax_[x][i-1],fmax_[to[x][i-1]][i-1]);}for(int i=0;i<a[x].size();i++){if(!dfn[a[x][i]])dfs(a[x][i],x);else if(dfn[a[x][i]]<dfn[x]&&a[x][i]!=fa) //出现返祖边(注意特判父亲!){int min1=1e9,max1=0,now=x;for(int j=20;j>=0;j--) //倍增求min1和max1{if(dfn[to[now][j]]>=dfn[a[x][i]]){min1=min(min1,fmin_[now][j]);max1=max(max1,fmax_[now][j]);now=to[now][j];}}pos[min1]=min(pos[min1],max1);  //求pos[]}}
}
int main()
{freopen("graph.in","r",stdin);freopen("graph.out","w",stdout);memset(pos,127,sizeof(pos));  //因为要取min,所以要赋值为INFscanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);a[u].push_back(v);   a[v].push_back(u);}dfs(1,0);    //预处理int hmin=1e9;       for(int i=n;i>=1;i--) //从n到1遍历方便求后缀最小值{hmin=min(hmin,pos[i]-1);//因为pos[i]肯定是小于等于n的,如果不是,就意味着该点没有出现在某个环的min1if(hmin>n) p[i]=n;     //如果后缀最小值大于n,说明没有限制,赋值为nelse p[i]=hmin;}for(int i=1;i<=n;i++)  //前缀和sp[i]=sp[i-1]+p[i];scanf("%d",&q);while(q--){int x,y;scanf("%d%d",&x,&y);	int l=x,r=y,k=0;   //肯定能够二分出至少一个p[j]>=ylong long ans=0;  //注意开long long!while(l<=r){int mid=(l+r)/2;if(p[mid]>=y) k=mid,r=mid-1;else l=mid+1;}ans=1ll*(y-k+2)*(y-k+1)/2;  //求>=k的贡献ans+=sp[k-1]-sp[x-1]-1ll*(k-x)*(x+k-3)/2; //求<k的贡献//求解的过程中可能爆int,注意用1ll*printf("%lld\n",ans);}return 0;
}

小细节

  • 前缀和数组和答案都需要开long long。求解的过程中也有可能爆 int,注意用1ll*(详见注释)。
  • 题目中说不存在一条边同时存在于两个不同的简单环,所以求环中点的 min1min1min1max1max1max1 的时候,直接暴力枚举整个环即可,每条边最多被遍历一次,O(m)O(m)O(m) 复杂度下即可求解。 我贴的代码是倍增的,时间复杂度反而更大了。
http://www.dtcms.com/a/355502.html

相关文章:

  • 【论文阅读】多功能肌电控制的新策略
  • Magnet Pro Macbook窗口分屏管理(Mac窗口分屏)
  • 安宝特方案丨AR异地专家远程支持平台,适合:机电运维、应急处置、监造验收
  • 光谱相机在雾霾监测中有何优势?
  • 测试题ansible临时命令模块
  • 自己定义的模型如何用hf的from_pretrained
  • Vue开发避坑:箭头函数与普通函数的正确使用指南
  • R 语言 eulerr 包绘制韦恩图:比例精准
  • 漫谈《数字图像处理》之区域生长和区域分离聚合
  • LeetCode100-41缺失的第一个正数
  • AI实时故障诊断系统(实时采集信号)
  • MySQL 中 tinyint(1)、int(11)、bigint(20) 的数字到底是什么意思?
  • (笔记)输入法框架协作机制深度分析
  • 内网穿透工具【frp】的核心功能底层处理逻辑解析
  • WINTRUST!_ExplodeMessage的作用是赋值psIndirectData
  • Windows 11 中 PowerShell 与 CMD 的深度对比:从定位到实战
  • 集成 A2A Protocol - BeeAI 框架的智能代理通信解决方案
  • 机器人芯片:驱动智能机器的核心技术引擎
  • 有限与无限的游戏 之感
  • 稳石氢能受邀出席2025势银绿氢产业大会,荣获“2025绿氢技术突破奖”!
  • SAP SD模块用户经常遇到的痛点以及解决方案
  • Circuitjs 测试点的使用
  • HTML+CSS、JavaScript、Vue、Ajax
  • Docker 40个自动化管理脚本-2 (40/40)
  • 【动态规划】子数组、子串问题
  • 国产芯力量!贴片式SD卡搭载北京君正Rk瑞芯微,打造嵌入式存储低延迟+高可靠黄金组合​
  • MongoDB 文档模型设计:JSON 结构的灵活性与陷阱
  • Mac训练大模型:MLX-LM框架LoRA训练Qwen3并集成SwanLab进行可视化
  • 基于mac的智能语音处理与应用开发-环境部署
  • 【LangGraph】核心概念速通:State/Node/Edge、通道、事件与流式输出