CF2018E2 Complex Segments (Hard Version) 题解
目录
题目描述
组数据,给定 条线段 ,称一个线段集合是复杂的,当且仅当:
- 它可以被划分成若干个大小相等的线段组。
- 两条线段相交当且仅当它们在同一组。
求用这 条线段构成的复杂线段集合大小的最大值。
数据范围
- 。
- 。
分析
记 为线段组大小为 时的最大组数,目标是求 的最大值。
显然 且单调递减,于是本质不同的 只有 种。接下来是经典的分治做法在 的时间复杂度内求所有 :
void solve(int l,int r,int L,int R)
{
if(l>r) return ;
if(L==R)
{
for(int i=l;i<=r;i++) f[i]=l;
return ;
}
int mid=(l+r)>>1,val=calc(mid);
f[mid]=val;
solve(l,mid-1,L,val);
solve(mid+1,r,val,R);
}
对于本题,将所有线段按照右端点从小到大扫描,维护每个位置被几条线段覆盖,线段树维护区间加区间 ,可以做到 计算单个 的值。
至此 已经可以通过 了,接下来是人类智慧。
先用基数排序操作一下,使得所有端点互不相同。
维护被覆盖次数为后缀 的所有下标 ,那么 被覆盖次数为 。
每次插入一条线段 ,我们将 加入下标集合,并删除 之前的最小下标。
并查集中 指向 (含)前面最后一个在 中的点即可。
时间复杂度 。
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pii pair<int,int>
using namespace std;
const int maxn=6e5+5;
int n,t,res;
int c[maxn],f[maxn];
pii p[maxn];
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
int calc(int m)
{
int cnt=0;
for(int i=1,x=0,cur=0,lim=0,lst=0;i<=n;i++)
{
int l=p[i].fi,r=p[i].se;
if(l<=lim) continue;
for(int j=lst+1;j<r;j++) f[j]=lst;
cur++,lst=f[r]=r,x=find(l);
if(x>lim) cur--,f[x]=x-1;
if(cur==m) cnt++,cur=0,lim=r;
}
res=max(res,cnt*m);
return cnt;
}
void solve(int l,int r,int L,int R)
{
if(l>r||L==R) return ;
int mid=(l+r)>>1,val=calc(mid);
solve(l,mid-1,L,val),solve(mid+1,r,val,R);
}
int main()
{
for(scanf("%d",&t);t--;)
{
scanf("%d",&n),memset(c,0,8*n),res=0;
for(int i=1;i<=n;i++) scanf("%d",&p[i].fi),c[p[i].fi]++;
for(int i=1;i<=n;i++) scanf("%d",&p[i].se),c[p[i].se]++;
for(int i=1;i<=2*n;i++) c[i]+=c[i-1];
for(int i=1;i<=n;i++) p[i].se=c[p[i].se]--;
for(int i=1;i<=n;i++) p[i].fi=c[p[i].fi]--;
sort(p+1,p+n+1,[&](pii x,pii y){return x.se<y.se;});
solve(1,n,n+1,0);
printf("%d\n",res);
}
return 0;
}
总结
- 3400 的 确实不好想,但 3300 的 绝对是虚高,场上有一些细节没处理好
呜呜呜。 - 且单调降,十有八九是自然根号,当然也可以用根号分治加二分做到 ,具体参见 的题解区。
本文来自博客园,作者:peiwenjun,转载请注明原文链接:https://www.cnblogs.com/peiwenjun/p/18442934
分类:
OI & ACM / 题解
, OI & ACM / 分治
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现