首页 > 其他分享 >Day-2

Day-2

时间:2024-02-18 14:35:07浏览次数:32  
标签:gcd ai 线段 区间 维护 Day log

栈, 队列

P6033

  • 操作:找min, 删min, 插入

  • 必须线性复杂度

    **特殊的性质:每次插入的元素单调递增 **, 即 b 单调

  • 两个队列:初始的 a, 合并后的 b, 都是有序的

    • 对 a 排序时使用桶排序(快排太慢)
  • 总共合并 n - 1 次, 每次 $O(1) $

P2827

  • 如果蚯蚓长度不变 -> 普通的优先队列(太慢)
    • 特殊性质:最长的蚯蚓在单调递减, 且分成的两段分别单调递减
    • 三个队列:原来的 a, px 的 b, x - px 的 c
  • 但是长度变化
    • 记录全局 tag
    • tag += q, 其他实际值不变, 新产生的 -q,
    • 再加上三个队列(仍然单调)
      • 原来的不变, 新加的原本就比原来的小, -q 后更小
  • $ O(n log n + m) $

并查集

P1197

  • 正着删边 -> 反向加边
    • 时光倒流

P2391

  • 线段树可以, 但是时间复杂度太大
  • 区间染色
    • 正着做会重复染多次
    • 所以倒着做
  • n 个位置, 每次找到没染色的位置, 就能得到均摊的 \(O(n)\)
    • 并查集
    • 对于染色的点, 父亲为左侧的点
    • 没染色的点父亲是自己
    • Find 一次, 找到从右到左第一个没染色的位置
  • 只路径压缩, 并查集是接近 $ O(n) $
  • 线性并查集
    • 将序列分成 log n 大小的块
    • 如果块内全是染色的, 就指向其左边的块
    • 否则指向自己
    • 块内的没染色点设为 1, 可以用类似 lowbit 的位运算 $O(1) $ 找
    • 只支持向自己左边连边

线段树

P3373

  • 双标记 -> 统一为一个
    • 规定一个顺序:先乘后加
  • 功能:信息合并, 区间修改, 查询
    • 信息合并:
      1. 信息 + 信息 -> 信息
      2. 标记 + 标记 -> 标记
      3. 标记 + 信息 -> 信息
  • × c + d & × a + b
    • (× a + b) × c + d = × ac + (bc + d)

P4513

  • 单点修改, 区间查询

    • 考虑信息合并
  • 维护最大前缀, 中缀, 后缀, 区间和

    • 合并后为 c, 原来为 a, b
    • c.maxpre = max(a.maxpre, a.sum + b.maxpre) (sum 的用途)

P7706

  • 单点修改, 区间询问

  • 转化为 找三元组(i, j, k), ai - bj + ak 最大(忽略min bj)

    1. 三元组全在左边
    2. 全在右边
    3. 跨过两个区间(左1右2, 左2右1)
      • 左边 ai(区间最大值), 右边 -bj + ak
      • 左边 ai - bj, 右边最大的 ak
      • 依赖于 a_max, b_min
    • 左边 i 元组, 右边 k - i 元组

P1471

  • 维护平方和, 和, 长度
  • \(\sum_{i = 1}^{n} (A_i - A_0)^2 = \sum A_i^2 - 2 * A_0 \sum A_i + n * A0 ^ 2\)
  • 可以合并

P6327

  • 函数
    • sin(\(\alpha\)) cos( \(\alpha\)) -> 库函数
  • image-20240216095623805

P4344

  • 维护 0 的前缀, 中缀, 后缀
    • opt0 区间全设为0
    • opt1 l0 -> r0 设为 0, l1 -> r1 从左到右填 l0 -> r0 个1(二分填的终点)
    • opt2 询问最大子段
  • $ O(m log ^2 n) $
  • (1 个 log????)

P5278

  • 找到 min, max
    • max - min = (r - l) * k (必要条件, 不是充分条件)
  • 区间所有数 % k 相同
    • b 是原数组 a 的差分数组
    • 等价于 l -> r 为 k 的倍数
      • 维护区间 gcd, gcd 应为 k 的倍数
  • 没有重复数字
    • pre i:i 左边第一个和他相同的数
    • pre i < l:无重复数
    • 维护区间 pre 的最大值
    • 修改时只影响 $ O(1) $ 个 pre
      • 对每个值开一个 set 维护下标
  • 以上 3 个条件是充要条件

P6617

  • 像上一题一样维护 pre[i] 表示 i 前面第一个 w - a[i]
    • 但是带修改
    • 一个 a[i] 可以对应多个 pre[j], 修改复杂度很大
    • 可以(根号分治???), 但是太麻烦
  • 只关心‘存在’
    • 有多个 pre 指向一个 a[i], 只把第一个指过去
  • 和上一个题类似

// 下午

Codechef DGCD 弱化

  • 标记(加法)和信息难以合并(常见难点)
  • Gcd 的特殊性质
    • 辗转相减法
    • gcd(a, b) = gcd(a - b, b)
      • gcd(a[l], ......a[r]) = gcd(a[l], b[l + 1]......b[r]), b 是 a 的差分数组
      • 区间加 -> 差分数组上单点加 -> [l] + v, [r + 1] + v

T367829

  • 最大的《子段平均数
  • 区间长不超过 3
    • c 分为 a, b 两部分, 则至少有一部分的平均数 >= c 的平均数, 假设是 a
    • 抛弃 b, 保留 a
    • 分成 2 和 x - 2 两部分, 则长度 -2 或变成 2
    • 100 1 100, 长度可能为 3
    • 得出:长度只可能为 2 或 3
  • 直接用线段树维护即可

CF280D

  • k = 1 最大子段和
  • 反悔贪心
    • 原来取了的位置允许被删掉
    • 去完后所有数都乘 -1 , 再求最大子段和
    • 对该子段取了的部分删掉, 没取的部分留下, 得到一个新的子段
      • 如果又去一遍, +1 和 -1 抵消, 相当于没取(反悔)
  • 标记合并:乘两次 -1 就抵消了
  • 信息合并:小白逛公园
  • 标记和信息:整个区间全乘 -1 或 全不变
    • 维护两种信息:乘 -1 的信息 和 不乘的(套路
    • (maxpre, maxsuf, maxmid) * 2 套

P3215

  • 删掉Swap操作

  • 未匹配的括号形如 ) ) ) ) ( ( ( (

  • replace???

  • invert 维护 反转后的信息, 没反转的信息(和上一题类似)

P4036

  • 删掉操作3

  • 线段树 + 哈希 + 二分

  • 弱化:单点修改, 查询是否相同

  • 线段树维护哈希:$ L * Base ^ {len_r} + R = Root$ $ O(1) $

  • 二分匹配的长度

  • $ O(m log ^ 2 n) $

// 均摊问题

经典问题

image-20240216144018742

  • 均摊
  • x = 1 无意义, x >= 2,
    • x = 2 时修改次数最多, 为 log 次
  • 每次修改不为 0 的数, 最多 n log n 次
  • 问题转化为求第一个非 0 位置的下标
    • 线段树 $ nlog ^ 2 n$
    • 并查集(上午讲的)$ n log n$

P4145

  • 每个数最多开平方有限次 就变成 1 了
    • 开平方的次数为 $ log log$ 次

CF438D

  • 打标记?

    • 不能合并
  • x % p

    • x >= p -> x % p
    • x < p -> 不变、
      • x >= 2p 减半
      • p <= x <= 2p 减半
  • 取模最多 log 次

  • 均摊 $ O((n + m)log V) $

  • 找到区间中 >= p 的值的位置

    • 每次找区间最大值, 如果 >= p 就对该位置取模, 否则停止执行
  • HDU 6315

    • b 是一个排列:$ \sum floor(ai / bi) = n * (1/1 + 1/2 + ... + 1/n) = n * log n $ (调和级数)
    • 维护 c 表示还要加多少 ai / bi 发生变化
    • 用线段树维护 c
    • $ O(n log ^ 2 n) $

P9989

  • 性质:
    • x 为 ai 的倍数:ai 不变
    • 否则 gcd(ai, x) <= ai / 2 (至少变成一半)
    • 最多取 log 次 gcd
  • 维护 lcm 判断该区间是否有结点不是 x 的约数
    • 在线段树上二分, 找一个是 log
  • lcm
    • lcm = a.mul * b.mul / gcd(a.gcd, b.gcd)
    • if lcm > 1e18 -> lcm = 1e18 + 1 (肯定不是 x 的约数)

LOJ 504

  • opt1 打一个对 k 取 max 的标记(将 a[i] 与 k 取 max)
  • opt2 最小的 x 个数 和 最小的一个数的区别
    • 找到区间最小值, 删掉(+1e18), 再求 x - 1 次
    • 删完后加回去
  • \(O(\sum x log n) = 2e6 * logn\)

下午总结

  • 更复杂的线段树和均摊问题

标签:gcd,ai,线段,区间,维护,Day,log
From: https://www.cnblogs.com/wangyangjena/p/18019256

相关文章

  • Day-3
    Dfs序CF383C简化:子树加,子树和(线段树+Dfs序)考虑对树做一个奇偶的分层x的深度为奇数,x子树中,深度为奇数+,深度为偶数-BZOJ3306小技巧:换根,Dfs序现在的根为x,原来的为rty在x的子树内->无影响y在x到根路径上->影响其他无影响if(Lca(x,......
  • day28 回溯算法part4 代码随想录算法训练营 78. 子集
    题目:78.子集我的感悟:看见弹幕是秒了,我有点不敢相信,自己试了试,没有通过,再看了一眼文字讲解。感觉懂了点理解难点:这题可以没有终止条件,开始我就疑惑这个终止条件怎么写注意这个nums[i]要添加进入是可以不写终止的,不会出现无线递归的,因为是从i+1开始,那会不会越界??,不会,最......
  • day28 回溯算法part4 代码随想录算法训练营 93. 复原 IP 地址
    题目:93.复原IP地址我的感悟:加油!理解难点:开始没理解,start_index的含义start_index是切割后的位置信息。代码难点:代码示例:fromtypingimportListclassSolution:defrestoreIpAddresses(self,s:str)->List[str]:#找3个分割点?#最后......
  • winter week3 day1
    2024牛客寒假算法基础集训营2ATokitsukazeandBracelet#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong//#defineint__int128#definedoublelongdoubletypedefpair<int,int>PII;typedefpair<string,int>PSI;typedefpair<stri......
  • Day1
    未获得准确的时间。导致了迟到/(ㄒoㄒ)/~~结果错过了前面的小半节课,也是让人难受≧﹏≦。进入正题T1最优贸易简化版解题方法:分块倍增线段树并查集本次使用分块解决,其他方法见题目中的附件。$n$个城市分布在一条直线上,从$L$到$R$获得最大利润时$ans=max(a_......
  • 代码随想录 day53 买卖股票的最佳时机
    买卖股票的最佳时机这里可以用贪心的思路因为只需要买卖各一次股票所以找到最大最小值算区间差也可以这里用dpdp[i][0]表示持股的收益dp[i][1]表示不持股的收益各自各有一种情况是维持原状还有一种就是持股卖出或者不持股买入取max就可以这里用了两个单位的数组只......
  • P7167 [eJOI2020 Day1] Fountain-st表
    这个题目,可以看出每一个盘里的水往下流出的路径会是一样的,而且没有修改操作,所以我们可以预处理出每个盘里往下的路径,已经要下去所需要的水。那么首先需要寻找每个盘往下的第一个盘是那个。对于盘i来说,第一个盘j应满足$j>i&&D_j>D_i$,所以就可以想到用单调栈处理每个盘下第一......
  • 补题 DAY1
    P2146 [NOI2015]软件包管理器给你一棵树,两个操作:installx查询路径\(0\tox\)上的点权和,并将路径点权赋值为\(1\)unistallx查询\(x\)的子树点权和,并将子树点权赋值为\(0\)板子。恶心。点击查看代码#include<bits/stdc++.h>#defineintlonglongusingnam......
  • 代码随想录 day51 打家劫舍
    打家劫舍当前位置偷与不偷取决于上一家的状态也就是有递推式考虑dp当前位置如果偷就是找i-2的位置的钱+当前的nums[i]如果不偷就是i-2的钱两个情况取最大值初始值如果只有0或1家人就特殊处理2家及以上初始0就是nums[0]1就是max(nums[0],nums[1])打家劫舍I......
  • 代码随想录 day51 单词拆分
    单词拆分这里递推式的意义是dp[i]:字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。如果确定dp[j]是true,且[j,i]这个区间的子串出现在字典里,那么dp[i]一定是true。(j<i)。所以递推公式是if([j,i]这个区间的子串出现在字典里&&dp[j]是t......