zoukankan      html  css  js  c++  java
  • ynoi2018

    题解:

    全分块是啥操作啊。。

    而且都好难。。

    1.未来日记

    这个比较简单

    对每个块开个线段树维护权值

    $nsqrt{n}logn$

    这个会炸空间 并不能做。。。

    但还是说一下做法

    首先考虑分块

    然后在每个块上我们要支持单点修改,查区间第k大

    比较自然的想到了用线段树维护

    如果没有修改就是在$sqrt{n}$颗树上一起二分

    多了修改操作

    对于整块,我们考虑要打一个lazy标记 表示x颜色变成y

    考虑用并查集维护

    对于整块修改 $x--->y$这个操作 我们可以选择将x颜色指向y颜色

    而对于单点修改,我们要将这个点指向这个颜色

    所以我们的整体步骤是对每个点建立一个点,然后对存在的颜色建一个点

    然后每次修改 如果当前颜色和修改成的颜色存在,我们就将当前颜色指向修改成的颜色

    同时标记当前颜色不存在,如果修改成的颜色不存在,我们就新建一个点代表修改成的颜色

    然后会发现这些需要一个$n*sqrt{n}$的数组来记录每个颜色对应哪个节点

    ****然后莫名其妙思考了一下可撤销并查集为什么不能路径压缩 发现和这题没有任何关系

    这样子大概就可以了 但是空间是光线段树就算动态开点最差也要$4*nsqrt{n}logn$ 直接自闭了

    所以 我就选择看题解了

    只能说题解非常的妙啊。。。。。

    我们考虑$x--->y$这个操作(是个经典的启发式合并操作)

    如果y原本有元素才进行这个操作,这个操作最多进行n次

    另外 分块查第k大有分块的做法

    就是对值域和位置都分块

    cnt1[i][j]表示前i个块在第j个值域有多少

    cnt2[i][j]表示前i个块j个值有多少

    这样的话对于查询我们就可以先根号枚举值域

    然后确定值域之后再一个个值查过去

    对于零散部分一个指针扫过去就行了

    然后就按照前面说的 如果有y就重构

    现在的问题就剩下

    2.末日时在做什么?有没有空?可以来拯救吗?

     这个相对还是比较难的 要花多一点时间想

    首先分块,然后我们发现我们需要维护块内前缀/后缀最大值 以及块内的区间最大值

    我们考虑区间最大值我们可以分成长为$1,2,3$这样的形式

    对于相同长度的我们显然只需要保留极值就可以了

    现在问题变成了

    支持+k(其中k>0)然后查询$x[i]+i*k$的最大值

    比较显然的发现这个东西可以用凸包维护,然后在凸包上二分

    但是我们注意到k是单调递增的 所以我们可以把二分变成维护当前指针(因为指针也是单调的)

    这样子往往能把复杂度从$nlognsqrt{n}$(对应修改操作$O(klogn)$的)变成$nsqrt{nlogn}$或者从$nsqrt{nlogn}$变成$nsqrt{n}$(对应修改操作$O(k)$的)

    然后我们发现修改零碎块的时间还需要支持重构操作

    但是发现重构好像得$O((sqrt{n})^2)$啊。。。

    这个东西我想了很久并不会。。

    于是就去翻题解 kczno1的并没有说这里怎么做 洛谷上的比较详细

    https://www.luogu.org/problemnew/solution/P4680

    大致思路就是先分治,对于两个子区间内的显然直接合并

    对于跨越中点的 等同于维护(ax,ay)+(bx,by)的凸包

    然后有个叫闵科夫斯基和合并凸包的东西(我并不能百度到这个东西)

    大致就是利用如下两条性质

    1.一定是由两个凸包上的点合并而成

    2.令$(i,j)$表示第一个凸包的第i个点,第二个凸包的第j个点

    那么如果$(i,j)$在凸包上,$(a,b) (a<i,b>j) $一定不在凸包上(这里洛谷上那篇题解好像写的有点问题)

    上面两点的正确性其实只要画画图就能知道比较显然

    于是我们会发现现在我们要求的变成了一条从$(1,1)$-->$(n,m)$的路径 每次可以向上或者向右走

    那么我们就可以每次贪心的选择斜率较大的那个

    于是这样我们在$O(klogk)$完成了对凸包的重构

    然后设块大小为k,块数为m,修改次数和查询次数都为q

    这题的时间复杂度是

    $q*m+q*k*logk+q*sqrt{n}*n$ 其中$km=n$

    其中最后一项的意思代表由于重构操作产生了$nsqrt{n}$的最优端点移动

    然后均值不等式一下$k=n/logn$的时候复杂度最小为$nsqrt{nlogn}$

    洛谷上的卡常技巧感觉有两点还是比较好的

    $1.$当长度<k的时候可以直接n^2暴力求(这个在其他地方也有应用 比如fft)

    $2.$注意到尽管是部分修改但是区间最大值的长度一定也是单调递增的

    所以如果当前区间长度<这个值就可以直接结束了

    另外这题如果把区间修改变为单点修改

    可以用动态dp这种高科技(当然我并不准备学它 毕竟noipd2t3已经可以用这个东西做了)

    也可以直接线段树维护区间前缀/后缀最大值/区间最大子段 (就和这题一样)来做

    3.五彩斑斓的世界

    这道题不需要太难的套路,想到的话代码相对于上两题比较简单

    我们考虑将序列分为

    $0~x-1$ $x-2x$ $2x+1~INF$

    对于$0~x-1$

    发现对于$x~2x$这一段 修改之后是会影响前面的排序的

    而对于最后一段 修改之后对前面也是没有影响的

    另外我们发现x-2x这一段修改相当于至少/2

    所以这样的操作最多进行log次

    于是就可以操作了

  • 相关阅读:
    面向接口程序设计思想实践
    Block Chain Learning Notes
    ECMAScript 6.0
    Etcd Learning Notes
    Travis CI Build Continuous Integration
    Markdown Learning Notes
    SPRING MICROSERVICES IN ACTION
    Java Interview Questions Summary
    Node.js Learning Notes
    Apache Thrift Learning Notes
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9992625.html
Copyright © 2011-2022 走看看