题目来源:2025 Wuhan University of Technology Programming Contest

比赛链接:Dashboard - 2025 Wuhan University of Technology Programming Contest - Codeforces

题目大意:

Solution:

首先肯定要预处理出以每个节点为起点出发获得的分数。然后就可以把树上的问题变成普通序列区间上的问题处理了。

很显然:

MAX 的答案就是区间长度

MIN 的答案就是区间众数的出现次数(若有多个众数,只算单个众数的出现次数)

于是答案就分为两个部分,一个树上预处理,一个维护区间众数出现次数

第一部分可以树上启发式合并用一个 set 维护当前子树内的连续区间,一个 multiset 维护当前所有连续区间的长度。当我们每加入一个新的点时,合并左右临接的区间,于是我们维护的区间一定是不相交的。

至于第二部分,直接离线询问莫队处理即可。

(第一次打的时候不知道如何用 set 维护区间,用数组存区间端点,又加了一个 goodr 表示当前维护的所有右端点,过程相对复杂,容易错,但好在没怎么调试,把两种写法代码都放在下面。)

Code1:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;#define N 100005int n,m,cnt,B,res;
int a[N],st[N],bel[N],dfn[N],siz[N],son[N],id[N],w[N],num[N],ld[N],rd[N],col[N],tot[N]; // num是数字i出现的次数struct Edge
{int next,to;
}ed[N << 1];struct Query
{int l,r,id;
}q[N],ans[N];multiset<int> s,goodr; // goodr存的是有效右端点int max(int x,int y) { return x > y ? x : y ; }int cmp(Query x,Query y)
{if(bel[x.l] == bel[y.l]) return x.r < y.r ;return bel[x.l] < bel[y.l] ;
}void added(int u,int v)
{ed[++ cnt].next = st[u];ed[cnt].to = v;st[u] = cnt;return;
}void pdfs(int x,int fa)
{siz[x] = 1;dfn[x] = ++ cnt;id[cnt] = x;for (int i = st[x]; ~i ;i = ed[i].next){int rec = ed[i].to;if(rec == fa) continue;pdfs(rec,x);siz[x] += siz[rec];if(!son[x] || siz[rec] > siz[son[x]]) son[x] = rec;}return;
}void calc(int x)
{x = a[x];if(!num[x]){if(ld[x - 1] && rd[x + 1]){int lenl,lenr;lenl = x - ld[x - 1];lenr = rd[x + 1] - x;auto it = s.lower_bound(lenl);s.erase(it);it = s.lower_bound(lenr);s.erase(it);s.insert(lenl + lenr + 1);int tl,tr;tl = ld[x - 1];tr = rd[x + 1];ld[rd[x + 1]] = tl,rd[ld[x - 1]] = tr;ld[x - 1] = rd[x + 1] = 0;it = goodr.lower_bound(x - 1);goodr.erase(x - 1);}else if(ld[x - 1]){int len = x - ld[x - 1];auto it = s.lower_bound(len);s.erase(it);s.insert(len + 1);ld[x] = ld[x - 1];ld[x - 1] = 0;rd[ld[x]] = x;it = goodr.lower_bound(x - 1);goodr.erase(x - 1);goodr.insert(x);}else if(rd[x + 1]){int len = rd[x + 1] - x;auto it = s.lower_bound(len);s.erase(it);s.insert(len + 1);rd[x] = rd[x + 1];rd[x + 1] = 0;ld[rd[x]] = x;}else{ld[x] = rd[x] = x;s.insert(1);goodr.insert(x);}}++ num[x];return;
}void del(int x)
{x = a[x];-- num[x];if(!num[x]){auto it = goodr.lower_bound(x);int tr = *it;int tl = ld[tr];int len = tr - tl + 1;it = s.lower_bound(len);s.erase(it);if(tl < x){int lenl = x - tl;s.insert(lenl);rd[tl] = x - 1;ld[x - 1] = tl;goodr.insert(x - 1);}else rd[tl] = 0;if(tr > x){int lenr = tr - x;s.insert(lenr);ld[tr] = x + 1;rd[x + 1] = tr;}else{ld[tr] = 0;it = goodr.lower_bound(x);goodr.erase(it);}}return;
}void dfs(int x,int fa,int op)
{for (int i = st[x]; ~i ;i = ed[i].next){int rec = ed[i].to;if(rec == fa || rec == son[x]) continue;dfs(rec,x,0);}if(son[x]) dfs(son[x],x,1);calc(x);for (int i = st[x]; ~i ;i = ed[i].next){int rec = ed[i].to;if(rec == fa || rec == son[x]) continue;for (int j = dfn[rec];j <= dfn[rec] + siz[rec] - 1;++ j)calc(id[j]);}auto it = s.rbegin();w[x] = *it;if(!op){for (int i = dfn[x];i <= dfn[x] + siz[x] - 1;++ i)del(id[i]);}return;
}void add(int x)
{x = w[x];-- tot[col[x]];++ col[x];++ tot[col[x]];res = max(res,col[x]);return;
}void sub(int x)
{x = w[x];-- tot[col[x]];if(!tot[col[x]] && res == col[x]) -- res;-- col[x];++ tot[col[x]];return;
}int main()
{memset(st,-1,sizeof st);scanf("%d%d",&n,&m),cnt = res = 0,B = (int)sqrt(n);for (int i = 1;i <= n;++ i) scanf("%d",&a[i]),bel[i] = (i - 1) / B + 1;for (int i = 1,u,v;i < n;++ i)scanf("%d%d",&u,&v),added(u,v),added(v,u);cnt = 0;pdfs(1,0);dfs(1,0,1);for (int i = 1;i <= m;++ i)scanf("%d%d",&q[i].l,&q[i].r),q[i].id = i;sort(q + 1,q + m + 1,cmp);int l,r;l = 1,r = 0;for (int i = 1;i <= m;++ i){while (l > q[i].l) add(-- l);while (l < q[i].l) sub(l ++);while (r < q[i].r) add(++ r);while (r > q[i].r) sub(r --);ans[q[i].id].l = res;ans[q[i].id].r = r - l + 1;}for (int i = 1;i <= m;++ i) printf("%d %d\n",ans[i].l,ans[i].r);return 0;
}

Code2:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;#define N 100005int n,m,cnt,B,res;
int a[N],st[N],bel[N],dfn[N],siz[N],son[N],id[N],w[N],num[N],ld[N],rd[N],col[N],tot[N];struct Edge
{int next,to;
}ed[N << 1];struct Query
{int l,r,id;
}q[N],ans[N];multiset<int> len;
set<pair <int,int> > s;int max(int x,int y) { return x > y ? x : y ; }int cmp(Query x,Query y)
{if(bel[x.l] == bel[y.l]) return x.r < y.r ;return bel[x.l] < bel[y.l] ;
}void added(int u,int v)
{ed[++ cnt].next = st[u];ed[cnt].to = v;st[u] = cnt;return;
}void pdfs(int x,int fa)
{siz[x] = 1;dfn[x] = ++ cnt;id[cnt] = x;for (int i = st[x]; ~i ;i = ed[i].next){int rec = ed[i].to;if(rec == fa) continue;pdfs(rec,x);siz[x] += siz[rec];if(!son[x] || siz[rec] > siz[son[x]]) son[x] = rec;}return;
}void calc(int x)
{x = a[x];int lenl,lenr;if(!num[x]){auto it = s.upper_bound({x,N});int flag = 0;if(it != s.end() && it != s.begin()){auto rseg = *it;-- it;auto lseg = *it;++ it;lenl = lseg.second - lseg.first + 1;lenr = rseg.second - rseg.first + 1;if(lseg.second == x - 1 && rseg.first == x + 1){auto itlen = len.lower_bound(lenl);len.erase(itlen);itlen = len.lower_bound(lenr);len.erase(itlen);len.insert(lenl + lenr + 1);s.erase({lseg.first,lseg.second});s.erase({rseg.first,rseg.second});s.insert({lseg.first,rseg.second});flag = 1;}}if(!flag){if(it != s.end()){auto rseg = *it;lenr = rseg.second - rseg.first + 1;if(rseg.first == x + 1){auto itlen = len.lower_bound(lenr);len.erase(itlen);len.insert(lenr + 1);s.erase({rseg.first,rseg.second});s.insert({x,rseg.second});flag = 1;}}if(!flag){if(it != s.begin()){-- it;auto lseg = *it;++ it;lenl = lseg.second - lseg.first + 1;if(lseg.second == x - 1){auto itlen = len.lower_bound(lenl);len.erase(itlen);len.insert(lenl + 1);s.erase({lseg.first,lseg.second});s.insert({lseg.first,x});flag = 1;}}}if(!flag){s.insert({x,x});len.insert(1);}}}++ num[x];return;
}void del(int x)
{x = a[x];-- num[x];if(!num[x]){auto it = s.upper_bound({x,N});-- it;auto seg = *it;int lenl = x - seg.first;int lenr = seg.second - x;s.erase({seg.first,seg.second});if(seg.first < x && seg.second > x){auto itlen = len.lower_bound(lenl + lenr + 1);len.erase(itlen);len.insert(lenl);len.insert(lenr);s.insert({seg.first,x - 1});s.insert({x + 1,seg.second});}else if(seg.first < x){auto itlen = len.lower_bound(lenl + 1);len.erase(itlen);len.insert(lenl);s.insert({seg.first,x - 1});}else if(seg.second > x){auto itlen = len.lower_bound(lenr + 1);len.erase(itlen);len.insert(lenr);s.insert({x + 1,seg.second});}else{auto itlen = len.lower_bound(1);len.erase(itlen);}}return;
}void dfs(int x,int fa,int op)
{for (int i = st[x]; ~i ;i = ed[i].next){int rec = ed[i].to;if(rec == fa || rec == son[x]) continue;dfs(rec,x,0);}if(son[x]) dfs(son[x],x,1);calc(x);for (int i = st[x]; ~i ;i = ed[i].next){int rec = ed[i].to;if(rec == fa || rec == son[x]) continue;for (int j = dfn[rec];j <= dfn[rec] + siz[rec] - 1;++ j)calc(id[j]);}auto it = len.rbegin();w[x] = *it;if(!op){for (int i = dfn[x];i <= dfn[x] + siz[x] - 1;++ i)del(id[i]);}return;
}void add(int x)
{x = w[x];-- tot[col[x]];++ col[x];++ tot[col[x]];res = max(res,col[x]);return;
}void sub(int x)
{x = w[x];-- tot[col[x]];if(!tot[col[x]] && res == col[x]) -- res;-- col[x];++ tot[col[x]];return;
}int main()
{memset(st,-1,sizeof st);scanf("%d%d",&n,&m),cnt = res = 0,B = (int)sqrt(n);for (int i = 1;i <= n;++ i) scanf("%d",&a[i]),bel[i] = (i - 1) / B + 1;for (int i = 1,u,v;i < n;++ i)scanf("%d%d",&u,&v),added(u,v),added(v,u);cnt = 0;pdfs(1,0);dfs(1,0,1);for (int i = 1;i <= m;++ i)scanf("%d%d",&q[i].l,&q[i].r),q[i].id = i;sort(q + 1,q + m + 1,cmp);int l,r;l = 1,r = 0;for (int i = 1;i <= m;++ i){while (l > q[i].l) add(-- l);while (l < q[i].l) sub(l ++);while (r < q[i].r) add(++ r);while (r > q[i].r) sub(r --);ans[q[i].id].l = res;ans[q[i].id].r = r - l + 1;}for (int i = 1;i <= m;++ i) printf("%d %d\n",ans[i].l,ans[i].r);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95744.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95744.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/95744.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JCTools 无锁并发队列基础:ConcurrentCircularArrayQueue

ConcurrentCircularArrayQueue ConcurrentCircularArrayQueue 是一个抽象类&#xff0c;它为基于数组的并发循环队列提供了基础功能。从其命名可以看出几个关键特性&#xff1a;​​Concurrent​​&#xff1a;常指无锁并发。​​Circular Array​​&#xff1a;内部使用循环数…

力扣(LeetCode) ——622. 设计循环队列(C语言)

题目&#xff1a;622. 设计循环队列示例1&#xff1a; MyCircularQueue circularQueue new MyCircularQueue(3); // 设置长度为 3 circularQueue.enQueue(1); // 返回 true circularQueue.enQueue(2); // 返回 true circularQueue.enQueue(3); // 返回 true circularQueue.…

在JVM跑JavaScript脚本 | Oracle GraalJS 简介与实践

这是2024年初的 GraalVM 系列博文&#xff0c;当时写了大纲&#xff0c;知道一年半后的现在才得以完成发布&#x1f604; 1、概述 实话说&#xff0c;标题的场景为小众需求&#xff0c;日常开发基本用不到&#xff0c;我是最近在做一个低代码轮子玩具 app-meta 需要实现 FaaS&…

基于 EC 数据与大模型技术实现天气预报:从数据到上线的全栈方法

1. 先校准“EC 数据”与“AI 预报”的语境 EC 数据家族(常用) IFS/HRES:确定性全球模式,水平分辨率约 9 km,常用预报范围 10 天; IFS/ENS:51 成员集合预报,提供 15 天概率信息; ERA5:再分析数据,小时级、0.25,可追溯至 1940 年,用作训练/评测黄金基准。 AI 预报…

迭代器模式及优化

迭代器模式&#xff08;Iterator Pattern&#xff09;是一种行为型设计模式&#xff0c;用于提供一种统一的方式遍历聚合对象&#xff08;如集合、容器&#xff09;中的元素&#xff0c;而无需暴露对象的内部实现细节。它将遍历逻辑与聚合对象分离&#xff0c;使得遍历操作可以…

纯Qt手撕gb28181协议/gb28181协议服务端/gb28181协议设备端/gb28181设备模拟器/gb28181虚拟监控设备

一、前言说明 搞完onvif设备模拟器&#xff0c;总想着把28181设备模拟也实现&#xff0c;因为之前已经花了大力气把28181平台软件端实现了&#xff0c;为了实现这个组件&#xff0c;头发掉了一大把&#xff0c;专门把国标文档看了好几遍&#xff0c;逐行阅读&#xff0c;针对需…

【渗透实战】无下载器环境(curl/wget)下玩转 Metasploit 自动利用

1. 背景与问题场景 在渗透测试或漏洞利用中&#xff0c;Metasploit&#xff08;MSF&#xff09;是业界最常用的框架之一。 其许多 RCE&#xff08;远程代码执行&#xff09;模块在落地 payload&#xff08;如 Meterpreter 或反弹 shell&#xff09;时&#xff0c;采用了 CMD St…

jd-hotkey探测热点key

对任意突发性的无法预先感知的热点数据&#xff0c;包括并不限于热点数据&#xff08;如突发大量请求同一个商品&#xff09;、热用户&#xff08;如恶意爬虫刷子&#xff09;、热接口&#xff08;突发海量请求同一个接口&#xff09;等&#xff0c;进行毫秒级精准探测到。然后…

C#WPF实战出真汁07--【系统设置】--菜品类型设置

1、菜品设置介绍 菜品设置跟餐桌设置的功能目的是相同的&#xff0c;包括了新增&#xff0c;删除&#xff0c;编辑&#xff0c;分页&#xff0c;查询&#xff0c;重置&#xff0c;全选&#xff0c;全消&#xff0c;列表功能&#xff0c;实现流程也是布局设计&#xff0c;后台逻…

aave v3 存款与借款利息的计算方式

本文只涉及到利率计算的数学原理&#xff0c;不作源码解析:存款首先我们假设小明在aave里面存了10000usdt&#xff0c;存的时候年化收益率是5%,那么半年后其存款的利息是多少呢?常规的计算方式如下:利息10000*5%*(存款的时长/一年的时长)这么做有什么问题呢&#xff1f;假设现…

Windows MCP.Net:基于.NET的Windows桌面自动化MCP服务器深度解析

&#x1f4cb; 目录 项目概述 技术架构深度解析 核心功能模块详解 代码实现分析 使用场景与实战案例 性能优化与最佳实践 扩展开发指南 总结与展望 项目概述 什么是Windows-MCP.Net&#xff1f; Windows MCP.Net是一个基于.NET 10.0开发的Windows桌面自动化MCP&…

Boost.Asio学习(7):Boost.Beast实现简易http服务器

namespace beast boost::beast;beast::flat_buffer是一个用于 Boost.Asio 和 Boost.Beast 网络读写的缓冲区实现。专为 一次性顺序读取 / 消费 场景设计&#xff0c;比 std::string 或 std::vector 高效&#xff0c;因为它是扁平内存结构&#xff08;contiguous memory&#x…

深入解析JVM内存区域划分:从理论到实践

Java虚拟机&#xff08;JVM&#xff09;是Java程序运行的核心环境&#xff0c;它负责管理内存分配、垃圾回收、字节码执行等关键任务。理解JVM的内存区域划分&#xff0c;对于优化Java应用性能、排查内存问题&#xff08;如OutOfMemoryError、StackOverflowError&#xff09;至…

滑窗|贪心|✅滚动数组

lc17.08pair按身高升序、相同时体重降序排序结果是找体重序列的最长递增子序列长度核心&#xff1a;转化为二维最长递增子序列问题求解vector<int> dp;for (auto& p : hw) {int w p.second;auto it lower_bound(dp.begin(), dp.end(), w);if (it dp.end()) {dp.pu…

深入理解数据库架构:从原理到实践的完整指南

一、数据库存储架构的多维度分类体系 1.1 基于数据组织方式的存储架构分类 数据库的存储架构从根本上决定了其性能特征、适用场景和扩展能力。理解不同的数据组织方式是选择合适数据库技术的基础&#xff0c;这种分类不仅反映了技术实现的差异&#xff0c;更体现了对不同业务需…

体彩排列三第2025218期号码分析

大家好&#xff0c;本人蔡楚门来此平台分享一下本期得经验和思路&#xff0c;希望能够给大家带来好的运气和灵感&#xff01;体彩排列三第2025218期号码分析&#xff0c;大小号码数字分析&#xff0c;上期开出全小号码最多&#xff0c;最近两期的开奖号码全部都是全小号码最多&…

java设计模式之迪米特法则介绍与说明

一、核心概念与目标 基本定义 迪米特法则的核心思想是&#xff1a;一个对象应该对其他对象尽可能少地了解&#xff0c;仅与直接关联的对象&#xff08;即“朋友”&#xff09;通信&#xff0c;避免与“陌生人”产生直接交互。 直接朋友&#xff1a;包括当前对象的成员变量、方法…

2024-2025华为ICT大赛中国区 实践赛昇腾AI赛道(高职组)全国总决赛 理论部分真题+解析

Part 1 昇腾AI全栈系统模块(共6题)&#xff1a;1、许多计算芯片可以设计作为人工智能的计算芯片&#xff0c;但不同的芯片计算性能不同&#xff0c;昇腾计算芯片是一种()芯片。(单选题)A.CPU B.GPU C. NPU D.TPU正确答案&#xff1a;C解析&#xff1a;A项CPU中央处理器的架…

网络安全和基础设施安全局 (CISA) 表示微分段不再是可选的

网络安全和基础设施安全局 (CISA) 最近发布了一系列指导文件中的第一份&#xff0c;旨在帮助联邦机构实施微分段&#xff0c;作为其零信任架构 (ZTA) 战略的一部分&#xff0c;以遵守2022 年白宫的授权。 该文件《零信任中的微分段&#xff0c;第一部分&#xff1a;介绍和规划…

Spring Boot SseEmitter 重复请求问题深度分析与解决方案

1. 前言 在使用 Spring Boot 开发流式接口(Server-Sent Events)时,我们遇到了一个令人困惑的问题:每次 SseEmitter 完成后,都会触发第二次请求,导致重复请求检测机制误报。本文将详细记录问题的发现、分析过程以及最终的解决方案。 2. 系统架构背景 2.1 请求处理架构 …