• “蔚来杯“2022牛客暑期多校训练营4 E - Jobs (Hard Version)


    Jobs (Hard Version)

    昨晚 学弟来问我这道题,就浅浅理A了一下

    题意:
    给定 n = 1 e 6 n=1e6 n=1e6 个公司, q = 2 e 6 q=2e6 q=2e6个人,每个公司有 m i m_i mi个岗位,且 ∑ i = 1 n m i = 1 e 6 \sum_{i=1}^{n}{m_i}=1e6 i=1nmi=1e6,每个岗位有 A , B , C A,B,C A,B,C 三个属性值,每个人有 a , b , c a,b,c a,b,c 三个属性值。一个人能够胜任这个岗位,当且仅当 A < = a A<=a A<=a && B < = b B<=b B<=b && C < = c C<=c C<=c A , a < = 400 , B , b < = 400 , C , c < = 400 A,a<=400,B,b<=400,C,c<=400 A,a<=400,B,b<=400,C,c<=400)。试求,对于每个人,他能在几个公司任职。(学弟给的题意,如果错了,请当这篇博客不存在

    思路:
    如果没有公司的限制,只是要求 每个人能够在几个岗位任职,就是简单的 三维偏序问题,直接 C D Q CDQ CDQ 即可,但是有公司的限制,就和种类数类似了,不能考虑 C D Q CDQ CDQ 了。

    但是可以借鉴 C D Q CDQ CDQ 的一些思路,比如,我们可以将所有岗位的 A , B , C A,B,C A,B,C 和 人的 a , b , c a,b,c a,b,c 放在一起,按照 a , A a,A a,A 的大小排序,那么 对于每个人,排在他前面的岗位 就是都满足 A A A 的条件的(也即 像 C D Q CDQ CDQ 一样,通过排序降一维)。

    这样处理之后,题目就转化成了,序列上 的 pair 对(B,C),对于每个人 j j j,需要求 有多少个公司,满足存在岗位 i, i < j ii<j && B i < = B j B_i<=B_j Bi<=Bj && C i < = C j C_i<=C_j Ci<=Cj 。因为求的是种类数,将同种类的岗位放在一起看,可以发现,对于两个不同的岗位 ( B , C ) (B,C) (B,C) ( b , c ) (b,c) (b,c) 如果 B < = b B<=b B<=b C < = c C<=c C<=c ,那么 ( b , c ) (b,c) (b,c) 是被 ( B , C ) (B,C) (B,C) 包含在内的,可以去掉。也即对于同种类的岗位,有效的岗位是一个 B B B升序, C C C降序的一个单调序列。发现了这个性质,那么离做出来也就不远了。

    然后,我们看对于每个人 j j j,我们需要求有多少个公司,满足存在岗位 i, i < j ii<j && B i < = B j B_i<=B_j Bi<=Bj && C i < = C j C_i<=C_j Ci<=Cj ,把 ( B , C ) (B,C) (B,C) 看成是一个平面,也就是求一个点的左下角有多少种类的点。我们可以维护一个 二维树状数组 t r tr tr t r [ x ] [ y ] tr[x][y] tr[x][y] 代表 ( x , y ) (x,y) (x,y) 的左下角的种类数;那么接下来就是怎么维护种类数了,对于每个公司维护一个单调序列,存 p a i r pair pair 的值,那么每次新进来一个 p a i r pair pair,可能会让对应单调序列 加入一个点 或者 删除一些点,当然不可能 f o r for for 单调序列,可以二分出这个 p a i r pair pair 要插入的位置。然后插入一个点或者删除一个点就在 二维树状数组上进行加减,当然不是在当前点的所有右上角进行加减,而是需要求出当前这个点和 单调序列的 前驱、后继 夹出来的特有矩形,在这上面执行操作。这样就能满足 对于一个特定的公司,对于二维平面上每个点 最多只贡献了 1。
    对于一个人只需要在全局的二维树状数组 查询一个给定点的值即可。
    (懒得画图了,有心人可以自己结合上文 画图理解一下)

    复杂度分析:
    M = ∑ i = 1 n m i M=\sum_{i=1}^{n}{m_i} M=i=1nmi
    对于每一个岗位都需要在单调序列中二分一下,因为 B < = 400 B<=400 B<=400,所以单调序列中最多只有 400个点,所以这部分的复杂度是 M ⋅ l o g 2 400 M·log_2{400} Mlog2400
    对于每个人,都需要在二维树状数组上查询一次值,这部分复杂度是 q ⋅ l o g 2 400 ⋅ l o g 2 400 q·log_2{400}·log_2{400} qlog2400log2400
    对于每个岗位在 单调序列上最多只会插入一次、删除一次,所以这部分复杂度是 M ⋅ l o g 2 400 ⋅ l o g 2 400 M·log_2{400}·log_2{400} Mlog2400log2400
    可以发现复杂度是 O ( 能过 ) O(能过) O(能过) 的,甚至绰绰有余吧。

    代码:
    因为笔者退役了,代码需要读者自行完成。
    当然上面只是口头理A,还有许多细节需要读者自己思考,比如:
    因为等式是 < = <= <= 的,所以排序之后需要 按照 B B B 值相等的分组, 先把所有的岗位都插入了,再去求答案。
    (如果学弟 写出来了,再把代码贴着吧)

    #include
    #include
    using namespace std;
    #define ll long long
    
    int main(){
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    碎碎:
    昨天晚上理A之后给学弟讲完,也算是感概万千,可能如果不退役,自己也能成为一名出色的金牌选手。
    这几天,也不知道自己在纠结什么,不知道是后悔还是不甘,也不知道自己喜欢acm是因为 做出题的愉悦,还是因为自己打的还算不错的底子,抑或是这两年在集训队的点滴。

    须知少时凌云志 曾许人间第一流

  • 相关阅读:
    js获取地址中携带的省市区
    2021-02-01
    uniapp editor组件添加插入超链接
    学js的第十五天
    C语言验证哥德巴赫猜想(ZZULIOJ1093:验证哥德巴赫猜想(函数专题))
    Day31|贪心算法1
    CSS读书笔记
    merge into 更新和插入
    java毕业设计OA办公系统mybatis+源码+调试部署+系统+数据库+lw
    【深度学习】吴恩达课程笔记(一)——深度学习概论、神经网络基础
  • 原文地址:https://blog.csdn.net/qq_52383696/article/details/126081338