• 一些ds题的题解


    collapse 题解:
    题目事实上让我们数连通块个数。
    一条边存在的时间肯定是一个区间。
    我们询问把连接(<p,geq p)的点的边删除后的结果,这可以被转化为询问一个前缀的点的导出子图的连通块数,加上后缀的点的导出子图构成的连通块数。
    后缀翻转后就是前缀,所以事实上我们需要询问一个前缀([1,p])的点的导出子图的连通块数。
    如果没有删边,则问题可以转化为:
    考虑被插入时间(t)小于等于现在时间(t1)的所有边对(x,y,x<y),数把(yleq p)的边插入后的连通块数。
    这事实上是二维偏序,是经典的HNOI2016最小公倍数问题,可以分块解决。
    但是我们维护的外部并查集只能算出([1,n])的连通块数。
    注意到(>p)的点都是孤立点,所以我们把答案减去(n-p)即可得到前缀的导出子图的连通块数。
    接下来考虑有删边的情况。
    假设现在扫描到时间维块(b),把边分成(4)类。
    第一类是在(b)内所有时间都存在的边,首先插入。
    第二类是插入时间/删除时间在这个块的边,显然这种边只会有(sqrt{n})个。
    第三类是在(b)内所有时间都不存在的边,不用管。
    显然在扫到块(b)时可以给每条边分类。
    考虑现在询问前缀([1,p])和时间(leq t1)的边,我们扫描第二类边集合。
    如果在当前时间(t1)现在扫到的边存在,则插入并查集,且更新连通块数。
    询问完后再全部撤销。
    在接下来扫到块(b+1)时,把并查集复原成所有点都是孤立点后,再插入下一个块的第一类边。
    时间复杂度(O((n+q)sqrt{n}log_2n))
    难度:中

    cat and dog题解:
    随便拿一个节点出来作为根。
    转化问题。
    考虑原树被删的边划分成的连通块。
    则每个连通块内最多只能有一个颜色的点。
    如果一个连通块存在某种颜色的点,则把它染成这种颜色。
    用dp解决这个问题,设(f_{i,0/1/2})表示当前(i)点所在的连通块是无色/白色/黑色,只考虑(i)和子树的点的最小代价。
    转移枚举当前点的颜色和当前点的每个儿子。
    如果儿子的颜色和当前相同,则不用删除当前点和儿子的边,否则需要。
    现在考虑多组询问,考虑树剖+线段树维护。
    一个节点的颜色变化显然只会影响到所有祖先的dp值。
    考虑从被修改的节点(x)向上跳父亲。
    对于每个节点,维护所有轻儿子的dp值更新当前节点。
    (未完待续)
    难度:易

    Chef and Churu题解:
    注意到单点修改,区间查询是个经典问题,可以用bit/分块解决。
    考虑对函数序列分块,查询时边角直接用bit解决。
    整块考虑维护整块的答案,然后(O(1))累加。
    在修改时要更新每一块的答案,设原来是(y),修改后是(z),那么每块的答案要加上(z-y)乘以当前块所有区间覆盖当前修改位置的次数。
    求出当前块的所有区间覆盖某个位置的次数很简单。
    (f_{i,j})表示第(i)(j)位置被覆盖的次数,显然可以差分求出(f)
    然而用bit时间复杂度带(log_2),所以用分块解决。
    难度:易

    时代的眼泪
    自己的做法有点奇怪,参考了区间逆序对的做法。
    设一个询问的矩形为((p1,p2),(p3,p4))
    定义(g(i,j))为顶部为(i),右部为(j),左/底部贴着平面的最左/最下边的答案
    由于问题比区间逆序对强,所以考虑分块。
    在分块时,序列被分为了(L,M,R)三个部分,(L,R)是左,右散块,(M)是中间整块。
    每个点的贡献是以它为左下角的矩形和询问矩形的交。
    (L,R)的贡献可以枚举(L)的每个节点,这样子贡献就是(R)平面上的一个子平面。
    把每个块内的(a)离散化后显然可以二维前缀和。
    为了避免二分,每个块(i)需要维护(f_{i,j})表示第(i)个块内小于(j)的最大数的排名。
    (L,M)(M,R)的贡献是对称的,所以只需要处理(L,M)的贡献。
    二维前缀和后,转化成了计算顶部任意,右部贴着某个块,左/底部贴着平面的最左/最下边的答案。
    (s_{i,j})表示右部为第(i)个块的右端点,顶部为(j)的答案,显然可以把前(i)个块内的点排序后求。
    (M)内部的每个节点的贡献可以被拆成在块内,块外的。
    块内的贡献事实上就是求块内的纵坐标在查询下界,上界的点的逆序对个数。
    一个块内最多只有(sqrt{n}*sqrt{n}=n)类贡献,可以通过前面的二维前缀和,枚举左端点,右端点递增处理。
    找下界,上界在这个块内对应的贡献类型可以用前面提到的(f)
    设当前最右的整块的右部横坐标为(p)
    设当前考虑的节点为(i)(i)所在块的右部横坐标为(q),扫描(M)的整块做处理。则我们要求矩形([(q,a_i+1),(p,p4)])内的点数。
    二维差分后变成(g(p,p4)-g(p,a_i)-g(q,p4)+g(q,a_i))
    (g(p,p4))(g(q,p4))贡献和(i)无关,显然可以用前面提到的二维前缀和求出(i)的个数。
    由于(p4)贴在块的右端点上,所以可以用前面提到的(s)求。
    (g(i,a_i))可以在块内维护一个前缀和(t)(t_i)表示(g(i,a_i)),找标号可以用以前的数组(f)
    (g(q,a_i))可以把这个块挂在(q)的块上。
    这事实上是一些点有权值,要求一个左部贴着某个块的左部,右部贴着某个块的右部平面的点的权值和。
    由于点权贴在块的右端点上,所以可以用前面提到的(s)求。
    可以给每个块再维护一个前缀和,然后扫描每个当前询问包含的块,用(f)求出标号后用前缀和求出答案。
    时间复杂度(O((n+m)sqrt{n})),感觉常数很大。
    难度:中

    lg7476
    考虑标记永久化,在每个节点上用一个堆维护标记。
    1操作就是区间加标记,3操作可以区间查询标记,每走到一个节点把答案和当前点的标记取最大值。
    子树标记最大值可以轻松维护。
    2操作有点麻烦,假设最大值为(x)
    在线段树上,我们可以把当前点拆成(log_2n)个区间,拆出的区间的祖先节点假如标记最大值(=x),则把祖先(=x)的标记弹出。
    把祖先的区间和查询区间取交,把祖先的区间减去交区间后,插入这个值为(x)的这个区间。
    在拆成线段树的区间后,我们可以在这个区间对应的点(p)上dfs,当(p)的子树没有(x)标记时(就是子树标记最大值不等于(x))就退出。
    由于标记只会弹出一个,所以在可以弹出时就可以退出了。
    时间复杂度是(O(nlog_2^2n+qlog_2n))
    难度:易

  • 相关阅读:
    16.小程序request请求
    15.小程序接入百度地图获取地理位置
    14. 微信小程序之wxss
    13.小程序视图层的模板
    es6字符串几个方法的理解
    记一次仿京东首页的轮播图效果
    ES6中Promise使用方法
    关于新版VS编辑环境下提示fopen不安全的问题报C4996错误的解决办法
    css布局拓展
    HTML的表单元素
  • 原文地址:https://www.cnblogs.com/ctmlpfs/p/15193254.html
Copyright © 2020-2023  润新知