首页 > 其他分享 >CF2018E2 Complex Segments (Hard Version) 题解

CF2018E2 Complex Segments (Hard Version) 题解

时间:2024-10-01 16:12:30浏览次数:7  
标签:le val int 题解 Segments mid Version solve 线段

题目描述

\(T\) 组数据,给定 \(n\) 条线段 \([l_i,r_i]\) ,称一个线段集合是复杂的,当且仅当:

  • 它可以被划分成若干个大小相等的线段组。
  • 两条线段相交当且仅当它们在同一组。

求用这 \(n\) 条线段构成的复杂线段集合的最大值。

数据范围

  • \(1\le n,\sum n\le 3\cdot 10^5\) 。
  • \(1\le l_i\le r_i\le 2n\) 。

分析

记 \(f(m)\) 为线段组大小为 \(m\) 时的最大组数,目标是求 \(m\cdot f(m)\) 的最大值。

显然 \(f(m)\le\lfloor\frac nm\rfloor\) 且单调递减,于是本质不同的 \(f(m)\) 只有 \(\mathcal O(\sqrt n)\) 种。接下来是经典的分治做法求所有 \(f(m)\) :

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);
}

对于本题,将所有线段按照右端点从小到大扫描,维护每个位置被几条线段覆盖,线段树维护区间加区间 \(\max\) ,可以做到 \(\mathcal O(n\log n)\) 计算单个 \(f(m)\) 的值。

至此 \(\mathcal O(n\sqrt n\log n)\) 已经可以通过 \(\texttt{E1}\) 了,接下来是人类智慧。

先用基数排序操作一下,使得所有端点互不相同。

维护被覆盖次数为后缀 \(\max\) 的所有下标 \(q_1,\cdots,q_k\) ,那么 \(q_i\) 被覆盖次数为 \(k+1-i\) 。

每次插入一条线段 \([l,r]\) ,我们将 \(r\) 加入下标集合,并删除 \(l\) 之前的最小下标。

并查集中 \(f_i\) 指向 \(i\) (含)前面最后一个在 \(q_1,\cdots,q_k\) 中的点即可。

时间复杂度 \(\mathcal O(n\sqrt n\alpha(n))\) 。

#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;
}

标签:le,val,int,题解,Segments,mid,Version,solve,线段
From: https://www.cnblogs.com/peiwenjun/p/18442934

相关文章

  • CF280C Game on Tree题解
    题目描述给定一棵有根树,结点编号从1到n。根结点为1号结点。对于每一次操作,等概率的选择一个尚未被删去的结点并将它及其子树全部删去。当所有结点被删除之后游戏结束。也就是说,删除1号结点后游戏即结束。要求求出删除所有结点的期望操作次数。不是哥们,我好不容易国庆......
  • 题解:AtCoder Beginner Contest AT_abc373_d ABC373D Hidden Weights(格式美化版)
    题目传送门题目翻译给你一个NNN个点,MMM条边的有向图,其中边有边......
  • CF429E Points and Segments 题解
    题目链接点击打开链接题目解法真难啊/yun把区间染成红色看作区间\(+1\),染成蓝色看作区间\(-1\),要求是每个点上的数\(\in\{-1,0,1\}\)可以选择的数有\(-1,1\)不太好做,我们考虑将限制变成每个点上的数只能为\(0\)我们记经过点\(x\)的线段数量为\(cnt_x\)如果\(cnt......
  • 题解:P11075 不等关系 加强版
    这是洛谷转移过来的题解,作者是4041nofoundGeoge(我自己,记得关注呀)题目大意对于一个字符串s1,s......
  • [HNOI2010] 城市建设 题解
    题意给定一个图,每次修改一条边的边权,每次修改后输出该图的最小生成树边权和,询问间不独立。思路在线不好做,考虑离线下来,可以使用线段树分治。我们称在当前区间\(\left[l,r\right]\)的边为动态边,不在的边为静态边。但这样每次遍历到叶子节点的时候静态边的数量都是\(m\)的......
  • 【洛谷】AT_abc079_d [ABC079D] Wall 的题解
    【洛谷】AT_abc079_d[ABC079D]Wall的题解洛谷传送门AT传送门题解不懂就问,为什么ABC很喜欢出板子题。经典的Floydqaq题目给出了一个二维数组和000~......
  • 题解 CF1785D - Range = √Sum
    link\(\texttt{Describe}\)构造有\(n\)个数的序列,满足以下条件:\(\foralli\in[1,n]\)并且\(1\lea_i\le10^9\)。对于任何的\(1\lei,j\len(i\nej)\),\(a_i\nea_j\)。\((\max_{i=1}^{n}a_i-\min_{i=1}^{n}a_i)^2=\sum_{i=1}^{n}a_i\)。......
  • vscode 运行 C++分文件显示 undefined reference to 问题解决
    一、问题无法关联到对应的方法。  二、结局方法1、第一步,查看.vsode文件夹里面的task.json文件;设置里面参数;${file}改成 ${fileDirname}\\*.cpp 2、第二步 2.1、打开coderunner的setting.json文件; 2.2、将 $fileName改成*.cpp 3.3、最后起哄一下vs......
  • 题解:P11062 【MX-X4-T2】「Jason-1」加法
    考虑两种情况:\(a,b\)符号相同:考虑经过操作后\(a,b,\lverta-b\rvert\)会变成什么。:\(a\)\(b\)\(\lverta-b\rvert\)操作1\(a+b\)\(b\)\(\lverta\rvert\)操作2\(a\)\(a+b\)\(\lvertb\rvert\)可以看出只进行零次或一次操作后可以取到最小值......
  • 题解:P11129 【MX-X5-T1】「GFOI Round 1」Inverted World
    题目要求:\((a_l+\cdots+a_r)\div(r-l+1)\)是整数。即\(\frac{(a_l+a_r)\cdot(r-l+1)\div2}{r-l+1}\)为整数。即\(\frac{(a_l+a_r)}{2}\)为整数。即\(a_l+a_r\)为偶数。即\(m+(l-1)\cdotd+m+(r-1)\cdotd\)为偶数。即\(2m+(l+r-2)\cdotd\)为偶......