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

洛谷 P11345 [KTSC 2023 R2] 基地简化 题解

校内模拟赛题,倒在了正解前最后一步 qwq。

解题思路

首先,发现题目要求的东西很不好做。于是转化一下,考虑计算每条边对答案贡献了几次。

这样问题就转化成了求有多少个区间的点分布在一条边两端的两个子树中。

发现这个东西还是不好求。于是正难则反,考虑计算区间的点全部在同一个子树里的区间数量。

显然,这个数量可以通过 set 维护子树内外点的编号所形成的连续段实现。但实现起来细节较多,需要注意各种边界问题。

如果暴力地对每棵子树都把节点挨个 insert 一下去算这个东西,复杂度就是 \(O(n^2 \log n)\) 的,会直接 T 飞。

我们使用树上启发式合并优化这个过程。时间复杂度 \(O(n \log^2 n)\)

Code

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i(a);i<b;++i)
#define rept(i,a,b) for(int i(a);i<=b;++i)
#define fi first
#define se second
#define int long long
using namespace std;
constexpr int N=3e5+5,P=1e9+7;
vector<pair<int,int>> g[N];
int n,tim;
int ans;
int l[N],r[N],siz[N],up[N],ch[N],rk[N];
signed maintenance_costs_sum(vector<signed> U,vector<signed> V,vector<signed> W);
inline int calc(int x){return x*(x+1)/2%P;
}
struct Set{set<pair<int,int>> s;int tot;void clear(){s.clear();s.emplace(1,n);tot=calc(n);}void insert(int x){auto it=prev(s.lower_bound({x,n+1}));int l=it->fi,r=it->se;if(l<x&&x<r){(tot-=calc(r-l+1))%=P;(tot+=calc(1))%=P;(tot+=calc(x-l))%=P;(tot+=calc(r-x))%=P;s.erase(it);s.emplace(l,x-1);s.emplace(x+1,r);return;}int lm=it==s.begin()?0:prev(it)->se;int rm=next(it)==s.end()?n+1:next(it)->fi;if(l==r){(tot-=calc(l-lm-1))%=P;(tot-=calc(rm-r-1))%=P;(tot-=calc(1))%=P;(tot+=calc(rm-lm-1))%=P;s.erase(it);return;}if(l==x){(tot-=calc(r-l+1))%=P;(tot-=calc(l-lm-1))%=P;(tot+=calc(r-l))%=P;(tot+=calc(l-lm))%=P;s.erase(it);s.emplace(l+1,r);return;}if(r==x){(tot-=calc(r-l+1))%=P;(tot-=calc(rm-r-1))%=P;(tot+=calc(r-l))%=P;(tot+=calc(rm-r))%=P;s.erase(it);s.emplace(l,r-1);}}
}st;
void add(int l,int r){rept(i,l,r){st.insert(rk[i]);}
}
void dfs(int u,int pre){l[u]=++tim,rk[l[u]]=u,siz[u]=1;for(auto [v,w]:g[u]){if(v==pre) continue;up[v]=w;dfs(v,u);siz[u]+=siz[v];if(siz[ch[u]]<siz[v]) ch[u]=v;}r[u]=tim;
}
void dsu(int u,int pre){st.clear();for(auto [v,w]:g[u]){if(v==pre||v==ch[u]) continue;dsu(v,u);st.clear();}if(ch[u]) dsu(ch[u],u);for(auto [v,w]:g[u]){if(v==pre||v==ch[u]) continue;add(l[v],r[v]);}add(l[u],l[u]);(ans+=up[u]*(calc(n)-st.tot))%=P;
}
signed maintenance_costs_sum(vector<signed> U,vector<signed> V,vector<signed> W){n=U.size()+1;rep(i,0,n-1){int u=U[i]+1,v=V[i]+1,w=W[i];g[u].emplace_back(v,w);g[v].emplace_back(u,w);}dfs(1,0);dsu(1,0);return (ans+P)%P;
}
http://www.jsqmd.com/news/64484/

相关文章:

  • Visual Studio Installer 2022正在进行准备
  • 在keil 中使用__attribute__关键字实现静态加载
  • ANCEL AS100 OBD2 Scanner: Full EOBD/OBDII/CAN BMW Check Engine Light Diagnostic Tool
  • 2025最新广东餐饮生鲜配送服务商/厂家TOP5推荐!深圳/广州/佛山/东莞全覆盖,全品类供应+一体化服务权威榜单发布,赋能餐饮企业降本增效新生态
  • FOXWELL NT809BT OBD2 BiDirectional Scan Tool: All Systems Diagnostics + 30+ Resets for EU/US Cars
  • SSM文创产品推荐环境设计与实现95ml5(工具+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,框架界面在末了面。
  • obsidian dataviewjs查找冗余文件
  • 模板索引 字符串
  • 2025.12.6日22:51-patriarchal家长的;族长的;由族长统治的
  • 2025最新深圳餐饮食材配送服务商/厂家TOP5推荐!全品类供应+一体化服务权威榜单发布,赋能餐饮企业降本增效新生态
  • 数据采集与融合技术作业4
  • Last Dance
  • 责任链模式
  • 树基础
  • [模板] 字符串
  • AT_agc002_d 题解
  • smartbits是啥
  • 每日反思(2025年12月6号)
  • 12.6笔记
  • 【亲测免费】 开源项目html2image常见问题解决方案 - 详解
  • vxe-gantt 甘特图实现产品进度列表,自定义任务条样式和提示信息
  • 2025最新东莞简餐快餐菜品研发培训服务商/厂家TOP5评测!全链条赋能+实战落地权威榜单发布,助力餐饮品牌破解同质化难题
  • 2024 MUCAR BT200 PRO OBD2 Scanner: Full System Diagnostic 15 Resets Wireless Code Reader
  • 数字马力二面准备-后端开发郑州岗(校招)
  • 完整教程:新手做网站如何被百度快速收录教程
  • [豪の算法奇妙冒险] 代码随想录算法训练营第十五天 | 110-平衡二叉树、257-二叉树的所有路径、404-左叶子之和、222-完全二叉树的节点个数
  • 12月6日总结 - 作业----
  • 11.6
  • 触摸未来2025-11-09:万有力,图论革命 - 指南
  • Linux内核学习记录