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

P13690 [CEOI 2025] boardgames

P13690 [CEOI 2025] boardgames

描述

给定一张无向图,将点按编号划分成若干区间的导出子图,要求满足所有导出子图联通,求最小联通数。

思路

主要来自于 jiangly。

存在比较暴力的做法,依次找到极小的出现断开位置的块,进行递归处理,显然会被做到 \(n^2\)

对于这类似的划分,可以尝试启发式分裂。

如果我们可以在 \(min(a,b)\) 的时间里,将连通块划分成 \(a\)\(b\) 两个不联通的,进行处理,那确实是可以做到 \(\log\) 的,但是该问题,对于较大的连通块不方便进行删边操作。

可能可以使用LCT进行无脑处理,但是太不优美,这里存在比较优秀的做法。

对于分治的区间 \([l,r]\),选取中点 \(mid\),每次只保留 \(mid\) 的所在的区间,这样的分治只包含 \(\log\) 层,因为每次递归下去的长度是 \(\leq \frac{len}{2}\) 的。

但是还是存在删边的问题,我们一般使用可持久化并查集来做带删边的联通性问题,但是在该问题下,他左右两边都要进行撤销操作,我们发现从中间进行加边的时候,左右交错太密集和太稀疏都不是很对。

事实上可以使用二进制分组,我们可以发现这样做单层是 \(log\) 级别的,看上去整体是一个 \(log^2 n\),但是 jiangly 可以分析到整体 \(n\log n\),实现也比较快,加上并查集是一个 \(n log^2 n\) 的复杂度,可以通过。

注意到:应当按照边进行分治,每次添加点是 \(O(deg)\) 级别的,而添边是 \(O(1)\) 的,这样才能确保复杂度。

实现:

#include<bits/stdc++.h>
using namespace std;
vector<int> partition_players(int n, int m,vector<int> X,vector<int> Y);
const int maxm=2e5+5;
const int maxn=1e5+5;
struct edge{int x,y,id;
}e[(maxm+maxn)<<1];
set< pair<int,int> > st;
int vc[maxm+maxn];
int fa[maxn],siz[maxn];
int be[maxn],en[maxn];
inline int find(int x){return x==fa[x]?x:find(fa[x]);
}
struct node{int id,val,op;
};
stack<node> st1,st2;
struct seq{int l,r,op;
};
stack<seq> sta;
int tt;
int nl,nr;
inline void add(int l,int r){++tt;sta.push({l,r,tt});for(int i=l;i<=r;i++){st2.push({e[i].id,vc[e[i].id],tt});vc[e[i].id]++;if(vc[e[i].id]==2){int x=find(e[i].x),y=find(e[i].y);if(x!=y){if(siz[x]<siz[y]){st1.push({x,fa[x],tt});fa[x]=y;siz[y]+=siz[x];}else{st1.push({y,fa[y],tt});fa[y]=x;siz[x]+=siz[y];}}}}
}
inline void remove(int o){while(st1.size() && st1.top().op==o){siz[fa[st1.top().id]]-=siz[st1.top().id];fa[st1.top().id]=st1.top().val;st1.pop();}while(st2.size() && st2.top().op==o){vc[st2.top().id]=st2.top().val;st2.pop();}
}
int tw[(maxm+maxn)*2];
inline int get(int b){if(tw[b]) return tw[b];int ret=1;while(ret*2<=b) ret*=2;return tw[b]=ret;
}
inline void add_block(int bl,int br){while(bl || br){if(bl>br){int re=get(bl);add(nl-re,nl-1);nl-=re;bl-=re;}else{int re=get(br);add(nr+1,nr+re);nr+=re;br-=re;}}
}
inline void solve(int l,int r,int bl,int br){if(l==r){st.insert({l,r});return ;}int mid=(l+r)>>1;for(int i=l;i<=r;i++){fa[i]=i,siz[i]=1;}for(int i=bl;i<=br;i++) vc[e[i].id]=0;while(!sta.empty()) sta.pop();while(!st1.empty()) st1.pop();while(!st2.empty()) st2.pop();vector< pair<int,int> > sl;nl=be[mid],nr=en[mid];add(nl,nr);add_block(be[mid]-be[l],en[r]-en[mid]);int L=l,R=r;while(L!=R){bool flag=0;for(int i=1;i<=max(mid-L,R-mid);i++){if(L+i<=mid){if(find(L+i)!=find(L+i-1)){sl.push_back({L,L+i-1});while(1){seq tmp=sta.top();sta.pop();if(tmp.r<be[mid]){nl=tmp.r+1;remove(tmp.op);if(tmp.r+1>=be[L+i]) break;}else{nr=tmp.l-1;remove(tmp.op);}}L+=i;int bl=nl-be[L],br=en[R]-nr;add_block(bl,br);flag=1;break;}}if(R-i>=mid){if(find(R-i)!=find(R-i+1)){sl.push_back({R-i+1,R});while(1){seq tmp=sta.top();sta.pop();if(tmp.r<be[mid]){nl=tmp.r+1;remove(tmp.op);}else{nr=tmp.l-1;remove(tmp.op);if(tmp.l-1<=en[R-i]) break;}}R-=i;int bl=nl-be[L],br=en[R]-nr;add_block(bl,br);flag=1;break;}}}if(!flag) break;}st.insert({L,R});for(auto x:sl){solve(x.first,x.second,be[x.first],en[x.second]);}
}
inline bool cmp(edge x,edge y){if(x.x!=y.x) return x.x<y.x;return x.y<y.y;
}
int tot;
vector<int> partition_players(int n, int m,vector<int> X,vector<int> Y){for(int i=0;i<m;i++){e[++tot]={X[i]+1,Y[i]+1,i+1};e[++tot]={Y[i]+1,X[i]+1,i+1};}for(int i=1;i<=n;i++){int id=tot/2+1;e[++tot]={i,i,id};e[++tot]={i,i,id};}sort(e+1,e+tot+1,cmp);for(int i=1;i<=tot;i++){if(!be[e[i].x]) be[e[i].x]=i;en[e[i].x]=i;}solve(1,n,1,tot);vector<int> ans;for(auto x:st){ans.push_back(x.second-x.first+1);}return ans;
}
/*
int main(){int n,m;scanf("%d%d",&n,&m);vector<int> X,Y;X.resize(m),Y.resize(m);for(int i=0;i<m;i++) scanf("%d%d",&X[i],&Y[i]);vector<int> ans=partition_players(n,m,X,Y);printf("%d\n",(int)ans.size());for(auto x:ans) printf("%d ",x);return 0;
}
*/
http://www.hskmm.com/?act=detail&tid=27537

相关文章:

  • CSS
  • 关于jinja2的ssti模版注入的学习+过滤
  • WPF Epplus export 10M+ items in excel with multiple sheets batch by batch
  • [EGOI 2023] Guessing Game
  • CF2152G Query Jungle
  • [ROI 2018] Addition without carry
  • [THUPC 2025 决赛] Im Here
  • 解码Linux基础命令
  • 基于 C++ 的高雷诺数湍流直接数值模拟求解器设计与性能优化 - 实践
  • 由等概率(a,b)生成等概率(c,d)
  • AI/LLM应用安全与合规产品(AI安全网关|AI安全围栏|AI应用防火墙) 2025最新推荐
  • 10.8 CSP-S模拟27 改题记录
  • 《可复制的领导力》
  • 经营分析会 - 智慧园区
  • 自动评估问答模型的技术突破
  • Ivanti EPM移动版12.5.0.0身份验证绕过漏洞分析与利用
  • 运行Udacity的MPC控制项目指南(project_10)在Ubuntu 18.04环境下
  • 深入解析:Java 将 PDF 转换为 PDF/A:数字文档归档的基石
  • 入门正当时!MQTT协议轻量简洁,但应用绝不简单
  • 英语阅读
  • CF1832D2 Red-Blue Operations (Hard Version) 模拟赛题目分析
  • 网络流最小割,无向图建图法,求最小割点转换求最小割边
  • 实验1 C语言开发环境使用和数据类型、运算符、表达式
  • 深度学习概述 - -一叶知秋
  • 烧录神器来了!量产工具使用教程,新手也能秒懂
  • 看论文随笔Incendio: Priority-Based Scheduling for Alleviating Cold Start in Serverless Computing
  • C#性能优化基础:内存诊断(dump)
  • 2025年企业级LLM内容安全防护指南:鉴冰AI FENCE流式网关技术深度解析
  • 完整教程:FPGA学习笔记——图像处理之亮度调节(Gamma)
  • Kubernetes Ingress:管理集群外部访问的入口网关