写题-2023.09

2023.08.30

LGP3966 [TJOI2013]单词

题意:AC自动机求模式串出现个数,板子。

  • 注意将模式串用分隔符连为匹配串时,长度与字符是否越界。

LGP2444 [POI2000]病毒

题意:

给定 \(n\) 个模式串,求是否有循环字符串,使得循环节不包含模式串。

分析:

转化为求AC自动机上是否有环,使得环对应的字符串集合的子串集合与模式串集合无交集。

  • 非法状态的排除
    在判断当前状态是否可取时,注意可能有:某模式串为 \(S\) ,当前状态为 \(A+S+B\) ,不合法但未被标记。
    因此应当在维护 \(fail\) 指针时,依据 \(Str(fail_{i})\)\(Str(i)\) 的字串,若\(fail_{i}\) 有标记则将 \(i\) 打上标记。

  • 环的 dfs 查找
    维护当前节点是否被访问过与是否在搜索栈中,若访问了已在搜索栈中的点则为真,若访问了被访问的节点则为伪。
    若某点在环中,则访问它时一定可以到达环上包括它在内的所有点至少一次,因此若已访问则不必再访问,无论其是否在环中 (即,返回伪是因为通过或运算获取答案,不代表实际一定为伪)。

2023.08.31

LGP5840 [COCI2015] Divljak

题意:

给定模式串集合 \(S\) ,不断向 \(T\) 中添加字符串,并询问满足 \(T_{i}\) 包含 \(S_{x}\)\(T_{i}\) 个数。

分析:

考虑 \(fail\) 树的性质:对于树上某节点 \(u\) ,从根到 \(u\) 之间的任意节点 \(v_{i}\) 满足 \(Str(v_{i})\)\(Str(u)\) 的子串(后缀)。
因此问题转化为,每次插入时在 AC 自动机里匹配新字符串,对于经过的所有节点,在 \(fail\) 树上将 每个从根到它们的链 覆盖的并集里的节点,点权(包含 该节点表示的字符串 的匹配串数量)加一。

  • 树上链更新单点查询
    对于树上链加、单点查,可以转化为单点加、子树查询;含义为,每个节点点权 \(w_{i}\) 表示将从根到当前节点链上所有节点点权加 \(w_{i}\)
  • 树上更新多链并集
    对于求并,烤炉从根到 Lca 的点被加了两次,所以将所有点按 dfn 排序,将相邻两点的 Lca 点权减一,保证每个点被更新一次。

技巧:
dfn 序求 LCA 。先咕掉。

LGP3041 [USACO12JAN] Video Game G

题意:

给定 \(n\) 个模式串,求长为 \(k\) 的字符串中模式串最多出现多少次。

分析:

AC 自动机 DP 模板。
\(dp_{i,j}\) 表示从根出发走长度为 \(i\) ,当前在节点 \(j\) 的最大答案。\(dp[i+1][son_{j}] += dp[i][j]\)

  • 关于贡献累加
    \(t[u][i]\) 原本为零时,若累加贡献至 \(v=t[fail[u]][i]\) ,相当于对以已更新过的点进行了重复累加。

LGP4052 [JSOI2007] 文本生成器

题意:

求长为 \(m\) ,包含至少一个模式串的字符串方案数。

分析:

转化为求全部方案数减去不含模式串的方案数。状态同 T2 ,若当前点或目标点被标记则跳过。

  • 关于标记
    若当前节点在 \(fail\) 树上的父节点被标记,则当前点也应被标记。即 \(ed[u]\ |=ed[fail[u]];\)

2023.09.01

LGP3834 【模板】可持久化线段树 2

主席树(可持久化权值线段树)板子。

LGP3834 【模板】可持久化线段树 1

可持久化线段树(题里也叫可持久化数组)板子。

LGP2633 Count on a tree

题意:

树上路径点权第 &k& 大,强制在线。

分析:

主席树树上板子。考虑权值线段树上出现次数的可加减性,每个点以父亲节点为上一版本, $ sum_{u}+sum_{v}-sum_{lca}-sum_{fa[lca]} $ 即为答案。

  • tips: 强制在线的题,RE 了很可能是 WA 。

2023.09.06

CF1149D Counting Arrays

题意:

给定序列最大长度 \(n\) 和值域 \(m\)\(a_{i}\) 可删除当且仅当 \(\gcd(i,a_{i})=1\) ,删除后剩余数前移。求最多有多少数列删除顺序不唯一。

分析:

  1. \(\gcd(i,a_{i})=1\) ,在 \(i=1\) 时一定成立,则每个数列至少有一种仅删除队首的的方式。所以一个数列有不止一种删除方式,则存在 \(a_{i}\) 满足 \({\exists}\ j\in [1,i],\gcd(j,a_{i})=1\)

  2. 对于所有方案可以分为两类的方案数问题,可以考虑用所有情况减去所求情况的对立。具体地,转化为 求仅有一种删除方式的序列个数。

  3. 若 $ {\forall\ j\ \in [1,i],\gcd(j,a_{i})=1} $ ,考虑将数视作质因数的乘积,则有 $ {\forall}\ prime \in [1,i] , {p}\mid {a_{i}} $ ,因此 \(a_{i}\) 一定是所有小于 \(i\) 的质因数的乘积的倍数,$ \lfloor {\dfrac{m}{\Pi p_{i}}} \rfloor $ 即为所求。

  • 注意取模
    对于作为值域,因而不能在输入后直接取模的 \(m\) ,应在每次调用 \(m\) 的计算先对 \(m\) 进行取模,否则 \(m\) 最大为 \(10^{12}\) ,会炸 long long 。

CF627D Preorder Test

题意;

带点权无根树,求任意顺序访问根和子节点时,前 \(k\) 个数最小值的最大值。

分析:

  1. 最小值最大,以及点权不变,考虑二分答案,每次 DP 检测。

  2. 第一次维护子树内可返回(不存在点权小于 \(mid\) )的最多节点、不可返回的最大次大。

  3. 换根时,考虑内部是否能走完,以及外部是否能走完,四种情况。

模拟赛时写出了 \(O(n^{2}\log n)\) 暴力,换根没推出来。

一定要记得初始化的 dfs0 。

  • 从 Eon 处获得的启示

    善用函数封装。例如在本题中,用新值更新最大次大、查询最大或次大(当自己为父节点最大时应选择次大)。

2023.09.07

CF852I Dating

树上莫队板子。赛时一眼板子,然后发现自己压根不会,尝试从零开始构建,最后交了个不伦不类的最坏 \(O(nm)\) 的代码上去,只过了 \(O(n^2)\) 的点。

注意欧拉序 2 倍空间。

CF1304F2 Animal Observation (hard version)

简单版 CF1304F1

题意:

过于麻烦,略。大意:\(n\)\(m\) 列带点权矩阵,每行选一个点作为横 \(k\)\(2\) 的矩阵的左端点,问生成的矩阵覆盖的点权和最大值。

分析:

赛时一眼 DP 但是在硬啃树上莫队板子暴力都没有写。

\(dp[i][j]\) 表示在第 i 行第 j 列的最大答案。

考虑转移一共有三种:无交、上个点在左侧、上个点在右侧,写写式子,直接 \(O(nmk)\) 可过简单版。

加强版增加了 \(k\) 的范围。发现对于有交,可以把部分式子合并,转化成一部分只与上一个转移点 \(k\) 有关,一部分只与 \(j\) 有关,由于两个情况的可取位置随 \(j\) 单向移动,可以单调队列维护。无交部分分别维护前缀后缀最大值即可。

调的时候 RE 比较多。注意形如 \(j+k-1\) 的式子要和 \(m\) 取最小,单调队列封装的细节等。

code

话说洛谷这 RMJ 怎么总不好使/fn

2023.09.08

LGP2571 [SCOI2010]传送带

题意:有两条传送带 AB 和 CD ,在平面上、AB 上、CD 上各有一定速度,求从 A 到 D 的最短时间。

分析:

设路径为 A-E-F-D , 其中 E 、 F 分别在 AB 、 CD 上。都说一眼单峰函数(A-E-F-D 、 E-F-D ,后者为固定 E 时),不懂。

别人的证明,用了一点三角函数,转化成求另外一些线段长度和最小,很巧妙的方式。

如果认可单峰函数,那就三分套三分,实现比较板。

新学了三分,和二分很像。每次由 \(l,r\) 分出 三等分点 \(midl,midr\) ,对于三等分点较不优的一侧,舍去三等分点到边界的区间。

一定要善用函数封装,比如求答案和三分 \(l,r\)

题解里说粒子群优化可做,可以考虑改天学一学。

CF1404E Bricks

赛时一眼流,死磕 T1 没想。

题意:

\(n \times m\) 的矩阵,点有黑白两种。要求使用长任意、宽为 \(1\) 的长方形覆盖所有黑点,长方形不能重合,也不能覆盖白色点。求最少使用多少长方形。

分析:

将操作视为,由最初每个黑点覆盖一个正方形开始,每次选择一条黑点之间的边合并两个矩形,尽可能多选择边。

发现两条边不能同时选,当且仅当它们是连接在同一个黑点上的、一横一竖的两条边。对于这样的两条边,建边,表示不能同时选,于是形成了二分图(横边一组,竖边一组)。发现所求为:满足每条边两边都不被连的情况下,最多选择多少点,即最多合并多少块,减少多少条。所求即为二分图最大独立集。

\(\text{二分图最大匹配} = \text{二分图最小点覆盖} = |V| - \text{二分图最大独立集}\)

2023.09.11

LGP5787 二分图/【模板】线段树分治

板子,但是判定非二分图的思路很好。

题意:

给定一些在时间 \(l,r\) 内存在的边,问在每一时刻图是否是二分图。

分析:

如果一个图是二分图,则每次走一条边可以视作,从一个集合走到另一个集合,考虑将每个点拆成两个,记为 \(u_{0},u_{1}\) 若有奇环则会使 \(u_{0},u_{1}\) 在同一环内,可以用可撤销并查集维护,判断 \(u\) 的两点是否在一个并查集,等价于是否是二分图。

  • 注意给答案赋值的逻辑,以及栈的调用位置。

LGP4097 【模板】李超线段树/[HEOI2013]Segment

板子。但是因为细节调了很久。

  • 注意对线段求 \(k\)\(b\) 的时候要转 double ,否则精度不够(不转默认为整数除法)。

  • 注意承接函数返回值的变量类型。

  • 关于浮点数的大小判断

    若题目里要求,当两解相同时取编号最小,则需要使用 eps 判断是否相等;同理,更新最优线段时也应如此考虑。

CF237E Build String

五月份刷 CF 图论题的时候做的,也是 CF 上交的第一道题,当时不知道啥是网络流,写了个暴搜 过了前三个样例直接 T 。

题意:

给定字符串 \(T\)\(n\) 个字符串 \(S\) ,从 \(S\) 中选择字符构成 \(T\) 每个 \(S_{i}\) 有最大取字符量 \(a_{i}\) 和 费用 \(i\) ,求构造出 \(T\) 的最小花费。

分析:

比较水的费用流,从源点向每个 \(S_{i}\) 建边,流量为 \(\min({a_{i}},{|S_{i}|})\) ,费用为 \(i\) ;从每个 \(S_{i}\) 向字符建边,流量为 \(S_{i}\) 含有的该字符数量,费用为 \(0\) ;每个字符向汇点建边,流量为 \(T\) 中该字符的数量,费用为零。

LGP1896 [SCOI2005]互不侵犯

最开始没理解有点晕,第二天早上直接过了。

题意:

\(N \times N\) 的棋盘里面放 \(K\) 个国王,使他们互不攻击,共有多少种摆放方案。(国际象棋)\(N \leqslant 9 , K\leqslant N \times N\)

分析:

  1. 数据范围一眼状压,但是不会。看了题解,发现关键点在于每一行的状态可以表示。

  2. 设 dp_{i,j} 表示 前 i 行中,第 i 行放了 S_{j} 的状态,一共放了 l 个的方案数。

  3. 转移: 依次枚举 i , j , k , l ,分别表示 行、当前行状态、上一行状态、总共个数,最后一维的转移类似背包。

    \(dp[i][sj][l]+=dp[i-1][sk][l-cj];\)

发现会有很多不符合题意的单行状态,因此只记录合法状态,可以减小复杂度。

2023.09.12

LGP4688 [Ynoi2016]掉进兔子洞

题意:

一个长为 \(n\) 的序列 \(a\)。有 \(m\) 个询问,每次询问三个区间,把三个区间中同时出现的数一个一个删掉,问最后三个区间剩下的数的个数和,询问独立。

本人翻译:每次复制出三个集合,若 $\exists\ a \in S_{1} \cap S_{2} \cap S_{3} $ ,则从三个集合中都删去 \(a\),问最终 \(|S_{1}|+|S_{2}||S_{3}|\)

分析:

考虑将元素排序,离散化时元素赋值为排名(小于它的元素的个数加 \(1\)),则每一种元素都有其对应的一段位置,可以用 bitset 维护该位置是否有值,加/删时查一下桶里该元素个数即可。最后用 bitset 按位与,得到需要删去的数。

另外,不能直接开 \(10^5\)\(10^5\) 大小的 bitset ,所以将询问拆分,每次处理 \(25000\) 个。

注意,每次应为 ed=st+25000-1 ,减一。

LGP5268 [SNOI2017] 一个简单的询问

题意:

给你一个长度为 \(N\) 的序列 \(a_i\)\(1\leq i\leq N\),和 \(q\) 组询问,每组询问读入 \(l_1,r_1,l_2,r_2\),需输出

\[\sum\limits_{x=0}^\infty \text{get}(l_1,r_1,x)\times \text{get}(l_2,r_2,x) \]

\(\text{get}(l,r,x)\) 表示计算区间 \([l,r]\) 中,数字 \(x\) 出现了多少次。

分析:

考虑将 \(\text{get}(l,r,x)\) 拆成 \(\text{get}(1,r,x),\text{get}(1,l-1,x)\) 形式,设 \(\text{get}(1,i,x)\)\(S(i,x)\) ,则可以拆成 \(S(r_{1},x)S(r_{2},x) + S(l_{1}-1,x)S(l_{2}-1,x)+S(r_{1},x)S(l_{2}-1,x)+S(r_{2},x)S(l_{1}-1,x)\) 对于每个式子用莫队求一下,加和即可。

似乎可以用 map 优化,少一些查询,但不太会写和算,而且正常写也过了,就没加。

LGP1879 [USACO06NOV]Corn Fields G

题意:

\(n \times m\) 的牧场,每块地可种或不可种,种的地不能相邻。不限制种地数量。求有多少种方案。\(N ,M\le 12\)

分析:

很明显的状压。由于不需要考虑数量,仅记录当前行、当前行状态和方案数即可。

\(dp[i][j] \text{+=}\ dp[i-1][k] \ \ \ (j \& k = 0 )\)

LG P3749 [六省联考2017]寿司餐厅

题意过长,略

分析:

  1. 类型:最大权闭合子图。即对于所选的子图,所有点的所有出边

  2. 最大权闭合子图的一般解法:

    1. 对于每一种“物品”,若权值为正,则连一条 \(S\)\(i\) 的边,表示若想要避免 \(i\) 带来的后续影响,需要割掉这一条边,即不选这个物品,舍弃其权值;若权值为负,则向 \(T\) 连一条边权为权值的绝对值的边,表示若(因为选了前面的一些物品)选了当前物品,需要承担该物品带来的负收益。
    2. 对于 \(u\) 与选了 \(u\) 则必选的 \(v\) ,连 \((u,v,inf)\) 的边,由于此边不可能被割,所以能保证必选的实现。
    3. 最终用所有正收益(因为默认全选)减去最小割即最大流即为最大收益。

3.具体到本题,对于每一个 \(d_{i,j}(i<j)\) ,向 \(d_{i+1,j},d_{i,j-1}\) 连边,边权为 \(inf\) ,每个 \(d_{i,i}\) ,向 \(x_{i}\) 连边。每个 \(d_{i,j}(i<j)\) ,物品权值为 \(d_{i,j}\) ;每个 \(d_{i,i}\) ,权值为 \(d_{i,i}-x_{i}\) ;每个 \(i\) (编号),权值为 \(-i^2\)

另外,这题里 \(x_{i}\) 不一定小于 \(n\)

2023.09.13

LGP1361 小M的作物

题意:

有 n 种作物,每种作物可以种在两个耕地的一个里,有不同收益;有 m 个组合,若某组合作物都在同一个耕地则有额外收益。求最大收益。

分析:

答案转化为总收益减最小割。

每个物品向 S , T 连边,分别为两种地的收益;每个组合拆成两个点,每个点一边连源汇点,边权为收益,一边连作物, inf 。意为:对于每个物品,要舍弃 A 或 B 的一个收益;若未舍弃 A (或 B) 的收益,则需要舍弃 B (或 A )的组合收益。

LGP4313 文理分科

题意略

分析略

比较简单的最小割,和上一题基本相同。

LGP3604 美好的每一天

题意:

给定长为 \(n\) 的字符串,\(m\) 次询问区间内可以重组为回文串的子区间个数。\(|char|\le 26\)

分析:

  1. 首先想到,由于重构没有限制方式,则“可重组为回文串”等价于“区间内至多有一个只出现一次的字符”。然后不会了

  2. 对于“满足条件的子区间的数量”问题,若序列有区间可加减性,则可以考虑使用前缀和,转化为“任选两个值 \(\text{sum}_{i} , \text{sum}_{j}\) 满足条件的 \((i,j)\) 数对的个数\((i<j)\)” 的问题。

  3. 对于本题,可以将 \(\text{sum}\) 装入桶,变成经典的莫队问题。具体地,新增答案为所有的 \(a \oplus 2^i = x\)\(a\) 的个数,即 \(a=x \oplus 2^i\)\(a\) 的个数。还有 \(a = x\) 的。

另外,莫队 \(r=l-1\) 的状态为空。

2023.09.14

LGP4549 【模板】裴蜀定理

题意:

给定一个包含 \(n\) 个元素的整数序列 \(A\),记作 \(A_1,A_2,A_3,...,A_n\)
求另一个包含 \(n\) 个元素的待定整数序列 \(X\),记 \(S=\sum\limits_{i=1}^nA_i\times X_i\),使得 \(S>0\)\(S\) 尽可能的小。
对于 \(100\%\) 的数据,\(1 \le n \le 20\)\(|A_i| \le 10^5\),且 \(A\) 序列不全为 \(0\)

分析:

  1. 对于 \(n=2\),可视作求 \(a_1x_1+a_2x_2=c\) 的最小正值,而 \(c\) 的最小正值一定是 \(\gcd(x_1,x_2)\) (此处略去证明)。
  2. 考虑推广至 \(n\) 项。突然有点不懂了,改天回来补。
  3. 别人的证明,[关于最小正值](题解 P4549 【【模板】裴蜀定理】 - zyr 的 Blog - 洛谷博客 (luogu.com.cn)),[关于合并](关于裴蜀定理推广的证明 - SOAP - 洛谷博客 (luogu.com.cn))

LGP3951 [NOIP2017 提高组] 小凯的疑惑 / [蓝桥杯 2013 省] 买不到的数目

题意:

有两种面值的金币,两种面值均为正整数且彼此互素。每种有无数个。求无法准确支付的的价格的最大值。保证有解。

分析:

裴蜀定理中阐述了 \(ax+by=c\) 的 c 是否能被正整数 \(x,y\) 表示,最大不能表示的值为 \(ab-a-b\),证明略去。

LGP1082 [NOIP2012 提高组] 同余方程

题意:

求关于 $ x$ 的同余方程 $ a x \equiv 1 \pmod {b}$ 的最小正整数解。

分析:

显然的 exgcd 模板,\(ax\equiv\ 1\pmod{b}\ \Longleftrightarrow ax+by=1\)

另外,\(b\) 不一定是质数,不能用费马小定理。

LGP2613 【模板】有理数取余

题意:

\(bx\equiv a\pmod{19260817}\)\(x\)

\(0\leq a \leq 10^{10001}\)\(1 \leq b \leq 10^{10001}\),且 \(a, b\) 不同时是 \(19260817\) 的倍数。

分析:

转化为 \(bx\equiv 1\pmod{19260817}\ \Longleftrightarrow bx+py=\gcd(b,p)=1\),再将答案乘以 \(a\)

不过这个明显唯一解的题让判无解是几个意思……

LGP2158 [SDOI2008] 仪仗队

LGP2261 [CQOI2007] 余数求和

LGP5091 【模板】扩展欧拉定理

2023.09.18

LGP4777 【模板】扩展中国剩余定理(EXCRT)

板子。
long long 相乘会炸。

P3560 [POI2013] LAN-Colorful Chain

长度固定。
哈希。
关于随机数?

P3558 [POI2013] BAJ-Bytecomputer

仅 -1,0,1。为什么呢?
dp。

upd on 2023.09.25

首先,若仅考虑 \(a_{i-1}\)\(a_i\)\(a_{i-1} < a_i\)),发现操作次数仅与 \(a_i\) 有关而与 \(a_{i-1}\) 的值无关。因此,把一个数变得很大是不优的。具体地,每个数不应超过最大值,也不应低于最小值,即更改后的序列 \(a'\) 仍满足 \(\forall a'_i,\ a'_i \in \{ -1,0,1 \}\),而 \(a'\) 一定形如 \(-1,-1,-1...0,0,0...1,1,1\)

于是考虑 DP,设 \(dp[i][j]\) 表示将前 \(i\) 个数改为合法,第 \(i\) 个数最终改为 \(j\) 的最少花费。

转移时依次枚举 \(i\)\(j\),设 \(d=j-a_i\)\(d=0\) 直接从前一位小于等于 \(a_i\) 转移,而由于序列中只有 \(-1,0,1\),所以 \(d>0\) 只能由前一位为 \(1\) 转移来,\(d<0\) 只能由前一位为 \(-1\) 转移来。简单分讨即可。

P3550 [POI2013] TAK-Taxis

贪心。
注意判断的先后顺序。

upd on 2023.09.25

一道贪心。

设当前位置为 \(j\)
把过程分为两个部分:\(j < d\) 的和 \(j \ge d\) 的。

\(j \ge d\) 的,由一辆不小于 \(d\) 的车直接送走最优。
\(j < d\) 的,由于每次要先走 \(d-j\) 的路程,剩下的才是贡献,所以应该使 \(d-j\) “尽快地”减小,所以每次应该先选路程最大的车。

于是贪心策略整理如下:
预留一辆最小的不小于 \(d\) 的车处理 \(j \ge d\) 的情况,之后从大到小选择车辆,每次分讨一下。
需要注意,因为留了一辆车没有使用,所以需要每次判断是否可以用预留车直接结束。

具体地,按路程从大到小:

  1. 如果当前是预留的车就跳过、
  2. 如果预留的车能直接结束就结束。
  3. 如果当前车不能使人前进则无解。
  4. 使用当前车改变 \(j\)
  5. 如果 j>=m$ 结束。

P3551 [POI2013] USU-Take-out

一定有解,可反证。
所以考虑倒序构造,用栈加前缀和维护。

upd on 2023.09.25

首先,由于每次消除不能路过已经消过的块,所以每次操作的序列一定在上一次操作的某两个位置之间。因此,将方案倒序观察,发现每次相当于从中抽出连续的 \(k+1\) 个,并将剩余块拼在一起。

其次,对于任意一个白块数量使黑块数量 \(k\) 倍的状态,其一定有解。

可以采用反证法:

设存在一个状态,使得当前状态下无法进行任何消除,则对于任意黑块,其左右白块数量和少于 \(k\) 个。

可以转化为,在 \(mk\) 个白块中插入 \(m\) 个黑块,使得对于任意黑块,其左右两侧白块和小于 \(k\)

(这里“第 \(i\) 个 黑/白”指从左往右数第 \(i\) 个 黑/白)

无论第 \(1\) 个块放在哪,第 \(2\) 个块必须放在第 \(k\) 个白块之前;同样地,无论第 \(3\) 个块放在哪,第四个黑块必须放在第 \(2k\) 个白块之前……

形式化地,为满足序列到第 \(i\) 个黑块为止是无法消除的,一定满足第 \(i\) 个黑块的位置在第 \(\lceil \frac{i}{2} \rceil k\) 个白块之前,所以,末尾一定剩余了至少 $mk-\lceil \frac{m}{2} \rceil \times k +1 $ 个白块,因此,无法消除的状态是不存在的。

具体实现为,用栈存块并维护前缀黑块个数,若从末尾开始的 \(k+1\) 个块里只有一个黑块,则将这些块弹出并记录。正序记录倒序输出或倒序记录正序输出都可以。

2023.09.19

LGP4597 序列 sequence

似乎本来是带优化的 DP,但是可以用性质乱搞。

题意:

给定一个序列,每次操作可以把某个数 \(+1\) 或 \(−1\)。要求把序列变成非降数列。

分析:

    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        q.push(x);
        int y=q.top();
        if(x<y)
        {
            ans+=y-x;
            q.pop();q.push(x);
        }
    }

Zpair 的证明是简洁的:

堆里维护每个数最低可以降到多少,则每次将堆中最大值 \(y\) 减至当前值 \(y\),并加上花费 \(x-y\)。只有最低值大于当前值时才需要修改最低值。

赛时想的是转化为差分,发现每次加减相当于移动差分数组上的值,考虑网络流。注意需要把初始的数变成正的或者什么别的做法,以保证差分数组(第一个数)的正确性。

LGP5455 [THUPC2018] 弗雷兹的玩具商店

题意:

给你 \(n\)个物品,每个物品的花费为 \(c_i\),价值为 \(v_i\),每个物品可以买无数次。 再给你 \(m\) 个人,第 \(i\) 个人拥有的钱数为 \(i\)。 你需要支持三种操作:

  1. 把区间 \([l,r]\) 中的物品花费增加 ,如果操作后花费高于 \(m\) 就将其减去 \(m\)

  2. 把区间 \([l,r]\) 中的物品价值增加 。

  3. 求出 \(m\) 个人在只买 \([l,r]\) 区间内的物品时,所有人能够获得的最大价值之和。

分析:

赛时想了很久,发现操作一相当于循环右移,于是线段树,每个点维护一个数组,\(w_i\) 记录价格为 \(i\) 的物品的最大价值,每次询问合并所有区间的数组,然后完全背包。虽然背包 \(O(qm^2)\) 但确实可过。

写的时候各种操作和所使用的变量能分开就分开,比如此题因为用 tmp 一边存答案一边 pushdown,调了一晚上。

2023.09.20

LGP3556 [POI2013] MOR-Tales of seafaring

题意:

\(n\) 个点 \(m\) 条边无向图,边权为 \(1\),每次询问两个点之间是否有长度为 \(d\) 的路径(不一定是简单路径)

分析:

首先想到,对于短于最短路径的一定不存在,其余的可能可以通过最短路加上 \(2\) 得到,即反复走刷步数。发现与奇偶有关。然后不会了。

考虑对于每个点维护奇数偶数的最短路,然后判断即可。离线处理(起点相同的一起查)。

实现:

SPFA 可以通过本题,复杂度应该是与 bfs 相同的吧。

LGP3557 [POI2013] GRA-Tower Defense Game

题意:

有一个 \(n\) 个点 \(m\) 条边的图,每条边距离是 \(1\) ,已知用 \(k\) 个攻击距离为 \(1\) 的塔可以打到整个地图,让构造一个方案使得用小于等于 \(k\) 个攻击距离为 \(2\) 的塔打到整个地图。

分析:

奇妙的思路。

发现由于不是求最小塔数,而是不多于 \(k\) 个,考虑性质。

若已经有 \((1,k)\) 的覆盖方式,则有:随意放置一个点,若不与 \((1,k)\) 的重合,则与至少一个相邻,可以覆盖到相邻位置的原先的塔所覆盖的全部位置。于是,无论怎么放,一定不会劣于 \(k\) 个,随意放置并记录即可。

实现:

似乎没什么细节。

LGP3554 [POI2013] LUK-Triumphal arch

题意:

给一颗 \(n\) 个节点的树(\(n \le 3 \times 10^5\)),初始时 \(1\) 号节点被染黑,其余是白的。两个人轮流操作,一开始 B 在 \(1\) 号节点。每一轮,A 选择 \(k\) 个点染黑,然后 B 走到一个相邻节点,如果 B 当前处于白点则 B 胜,否则当 A 将所有点染为黑点时 A 胜。求能让 A 获胜的最小的 \(k\)

分析:

显然二分是可以的。

另外,B 一定不会走回头路。

考虑每次染色必须先将 B 所在点的所有子结点染黑,而多余的次数可以染子树里需要提前染色即子结点数大于 \(mid\) 的点。

树形 DP,\(aside_i\) 表示以 \(i\) 为根的子树内需要子树外“支援”多少染色次数。最后检查 \(aside_1\) 是否为零即可。

实现:

DP 时注意,时刻保证 \(aside_i\) 非负,似乎许多人没有注意到。感觉时刻保证非负是比较合理且不容易出错的写法。

LGP3563 [POI2013] POL-Polarization

题意:

给定一颗树,请给树边改成有向边,求连通的点对个数的最大最小值。点对连通,要么 \(a\) 能到达 \(b\),要么 \(b\) 能到达 \(a\)\((1\le n\le 250000)\)

分析:

  1. 最小值
    1. 因为树是一个二分图,所以显然可以将所有边从左部指向右部,于是联通对的数量为边数。
    2. 也可以考虑每一层的边是相同指向,且与根结点相连的指向根结点,这会是除根结点外每个点能且仅能到达一个点。
    3. 综上,最小值为 \(n-1\)
  2. 最大值
    1. 首先有引理如下(不会证):
      对于一个使得联通点对最多的图,一定存在一个点,满足方案:以该点为根,每个子树内,要么所有边均指向根,要么均背向根。且根结点一定在重心上。

    2. 答案的第一部分:
      不经越过根节点的,易知数量为 \(\sum (size_i-1)\),意为新增了子树内其他点到根结点的贡献。

    3. 第二部分:经过根节点的

      1. 设指向根的子树总大小为 \(x\) ,背向根的子树总大小为 \(y\)。则所有 ”\(x\)“ 可以到达根节点再到达所有“\(y\)”。所以数量为 \(x \times y\)
      2. 若要使 \(x\times y\) 最大,一定是 \(x-y\) 最小时成立。实际为多重背包求(更接近 \(\dfrac{n}{2}\))对应值是否可以得到。
      3. DP 式子:\(dp[j]|=dp[j-i]\)\(dp[j]\) 表示当前值为 \(j\) 是否可取,\(i\) 表示大小为 \(i\) 的子树的值(其实就是 \(i\))。复杂度 \(O(n^2)\)
      4. 初步优化:二进制优化 01 背包。
      5. 复杂度分析
        发现树本身有性质:若子树少于 \(\sqrt{n}\) 个显然复杂度不劣于 \(O(n\sqrt{n})\)。若多于 \(\sqrt{n}\) 个,不妨想想怎么卡:如果有两个一样的显然会被合并,亏了,所以子树应两两不同,这样建树总点数为 \(\sum \limits_{i=1}^j\),而\(j<\sqrt{n}\)。综上,总复杂度为 \(O(n \sqrt n)\)
        6.进一步优化:bitset 优化连续二进制操作。具体地,操作改为 \(dp|=dp<<i\)。复杂度 \(O(\dfrac{n\sqrt n}{w})\)

实现:

注意重新以重心为根节点维护子树;最终用于背包的子树是重心的直接子树; \(dp|=dp<<i\) 进行 \(cnt[i]\) 次。

参考:

Solution By Tsawke

LGP3553 [POI2013] INS-Inspector

摘要:

  1. 二分 \(k\),每次沿时间轴检验前 \(mid\) 个是否冲突。
  2. 人的记录使他有一个必须存在的时间段。
  3. 逐时间点、尽可能使人数最少地满足记录要求,并检查是否使用超过 \(n\) 个人。

题意:

一天公司有 \(n\) 个员工和 \(m\) 个员工记录,每个员工只会在连续的一段时间内工作。现在给出 \(m\) 条记录分别是谁写的、什么时候写的以及写的时候除了他还有多少人。求最大的 \(k\) 使得前 \(k\) 条记录互不矛盾。

分析:

  1. 发现 \(k\) 似乎无法直接求得,考虑转化为检验前 \(k\) 条是否合法。

  2. 发现对于第 \(i+1\) 条记录,直接检验其与前 \(i\) 条是否冲突似乎不好实现,考虑每次检验 \(O(m)\) 地遍历全部时间点,因此需要二分 \(k\)

  3. 如何检验

    1. 由于每个员工工作时间连续,所以将记录整合可以得到每个人必须要工作的区间,后文简称“必要区间”,整合区间可以得到每个时间点至少有多少人,检验记录是否小于最小值。以及是否存在对于同一时刻有不同记录。
    2. 通过了 i 检测的所有情况中,每个时间点的记录人数大于等于实际人数,因此若不限制人数一定合法(即每个人只工作于一个时间点)。问题转化为尝试使用不多于 \(n\) 个人构造一个合法解。
    3. 沿时间轴检验并时刻判断即可,详见下文。个人认为本题难点是检测的思路和具体实现。
  4. 检验的实现

    1. 思路:尝试用最优方式满足限制,并记录使用了多少人,看是否超过 \(n\)
    2. 预处理:每个时间点 \(i\) 的记录人数、有多少人的“必要区间”以当前时间开始或结束;即 \(cnt_i,bg_i,ed_i\)
    3. 实现方案不唯一,部分名称含义如下:
      \(now\):当前至少要有多少人(由且仅由 \(st_i,ed_i\) 决定)。
      \(used\):已经使用过多少人。
      \(exl\):有多少人已经完成了必要区间,但是被迫延后下班。
      \(exr\):有多少人还没到必要区间,但是被迫提前上班。
      \(fre\):没有写记录的人,他们可以自由安排。
      \(left\):已经完成了工作,离开公司的人,后续安排与他们无关。
      注意,初始时认为上述全部为零;另外,上述名称在表述时也视作集合。
    4. 每一步的处理方法
      处理顺序:\(bg_i \rightarrow cnt_i \rightarrow ed_i\)。通过变量上的加减、逻辑上的人员调动(即从某一集合移动到另一集合),用 \(now,exl,exr\) 拼凑出 \(cnt_i\)
      1. 当前点至少有 \(bg_i\) 个人开始工作,逻辑上,要把 \(exr\) 或者 \(fre\) 拿出 \(bg_i\) 个转化为 \(now\),优先使用 \(exr\),不足则增加 \(used\)
      2. \(now+exl+exr\) 是当前我们构造的方案的人数,若其小于 \(cnt_i\),则需要从 \(fre\) 中抽调一些。因为\(now\) 是被 \(bg_i,ed_i\) 锁定的,所以把抽调的加在 \(exr\) 上,逻辑上为要求这些人提前工作。
      3. \(now+exl+exr\) 大于 \(cnt_i\),则先弹掉 \(exl\),仍多则弹掉 \(exr\)
      4. 在当前时间,有 \(ed_i\) 个人可以结束工作,让他们进入 \(exl\) 等待后续调度。
      5. 最后,判断 \(used\) 是否超限。把上述步骤循环 \(m\) 次即可。

实现:

采用了 \(now,used,exl,exr\) 实现,用 \(used \ge n\) 判断不合法,仅在每次结尾判断即可,中间不需要判哪些变量是不是负数,个人认为比较好写。

点击查看代码

    for(int i=1;i<=m;i++)
    {
        if(!t[i].vis)continue;

        now += t[i].bgcnt;

        if(now>t[i].cnt)
            return false;

        while (t[i].bgcnt--)
        {
            if(exr>0)exr--;
            else  used++;
        }

        if(now+exl+exr<t[i].cnt)
        {
            int d = t[i].cnt-now-exl-exr;
            exr+= d;  used+= d;
        }
        if(now+exl+exr>t[i].cnt)
        {
            int d = now+exl+exr-t[i].cnt;
            while(d--)
            {
                if(exl>0)exl--;
                else exr--;
            }
        }

        now-=t[i].edcnt; exl+=t[i].edcnt;

        if(used>n)
        {
            return false;
        }
    }

2023.09.21

LGT124433 【模板】哈希表

拉链法实现。注意 val 数组的类型和 cnt 数组。

可以用 tmeplate 实现支持多种类型。

然而似乎是不如平板电视的探测的,改天去 6Bit 发的 PDF 里学学那个库里的东西。

LGP3552 [POI2013] SPA-Walk

题意:

\(2^n\) 个长度为 \(n\) 的 01 串,两个 01 串之间有边当且仅当这两个 01 串只有一位不同,现在从这 \(2^n\) 个串中拿掉 \(k\) 个,问指定两个串之间能否到达。

分析:

会不了一点(虽然别的也不会),看了题解发现是神奇的定理题。

由 n=1,n=2,n=3 一步步想,可以看出是一类很神奇的图形,学名是 n 维超立方体。

  • Lemma1:

    将 n 维超立方体分成两部分,则连接两部分的边数不少于最少的那部分的点数。

    \(|E_{middle}| \ge \min(|V_1|,|V_2|)\)

    证明是有的,但是写完其他的再说,先咕掉。

  • Lemma2:

    去掉 n 维超立方体中任意 \(k\) 个点,剩下的点最多形成一个点数大于 \(nk+1\) 的连通块。

    \(\sum_{V_i \in V-V_k}\ [\ |V_i| > nk\ ] \le 1\)

    可以用引理1证明:

    假设把一个大于 \(nk\) 的这一部分拿出来,形成 \(|V_1|\ge nk+1,|V_2|\ge nk+1,|V'|\le 2^n-nk-1,|V_2|\in|V'|\),则连接两部分的边至少有 \(nk+1\) 条。然而,每个点连接了 \(n\) 条边,删去 \(k\) 个只能删去 \(nk\) 个,所以任意两个 \(V_1\)\(|V_2|\) 无法被分开,故不会有两个或更多。

  • 由上述引理,可以有以下分析:
    \(x,y\) 在同一个小于 的连通块里,bfs 至多 个点可以找到;若找完整个块没有找到说明不连通;若经过了超过 \(nk\) 个点未找到直接返回并记录,\(x,y\) 都属于这种状况可由引理 2 判断为连通。

  • 用 stl 说是过不了,选择手写哈希,被 lhy 强烈谴责不如平板电视。

upd on 2023.09.25

引理 1 找到了两个证明:

比较复杂的一个比较简洁的一个

简洁版是说,定义 \(x,y\) 的特殊路径为,顺次更改每一位,经过的路径,此处以从前往后为例。

经过某条边 \(u—v\) 的特殊路径有 \(2^{n-1}\) 条,证明如下。

【前半部分】【当前位置】【后半部分】

设路径 \(x,y\) 经过边 \(u—v\),,当从 \(x\) 走到 \(u\) 时,仅更改了前半部分的点,即 \(x\) 在当前位置以及后半部分与 \(u\),相同,是固定的;同理,\(y\) 的当前位置和前半部分也是固定的。即,只有 \(x\) 的前半部分与 \(y\) 的后半部分是任意的,相乘得到总共 \(2^{n-1}\)\(x,y\)

\(V\) 分成 \(S,T\) 两个无交集合,设 \(|S| \le |T|\),则集合间的特殊路径有 \(|S|(2^n-|S|)\) 条,因此集合间的边数为 \(\dfrac{|S|(2^n-|S|)}{2^{n-1}} \ge \dfrac{|S|2^{n-1}}{2^{n-1}}=|S|\)

复杂版留给读者。

实现:

注意哈希表要规范、正确。模数被误导设成(1<<i)-1(实际上是用于手写队列的循环),冲突大增,TLE 调一晚上没懂;没开 long long 又调半天。

2023.09.22

LGP3547 [POI2013] CEN-Price List

题意:

给定一个 \(n\) 个点 \(m\) 条边的无向图,边权均为 \(a\)

现在将原来图中满足最短路等于 \(2a\) 所有的点对 \((x,y)\) 之间加一条长度为 \(b\) 的无向边。

给定 \(k\),求点 \(k\) 到所有点的最短路是多少。

分析:

感觉不难,没懂为啥评黑。

\(dis_a,dis_b\) 表示只走 \(a\) 路径或 \(b\) 路径的步数。

一共有三种走法:\(dis_a \times a ,\ \lfloor \dfrac{dis_a}{2}\rfloor \times b \ + dis_a \bmod 2 ,\ dis_b \times b\)

前两种直接 bfs 即可。

\(u\)\(v\)\(w\),则由 bfs 的性质 (类似 dijkstra,此处由于边权记 1 保证了 dij 的优先性质),不会存在 \(u'\)\(v\)\(w\) 而优于 \(u\)。因此每次若 \(w\) 不和 \(u\) 相连,即可更新 \(w\)\(dis_b\),并删去 \(v\)\(w\) 的边(分两层,一层为基础,一层可删)。

对于所有的边:删去的只访问一遍,\(O(m)\);不可删等价于三元环,每个三元环的每条边常数遍,而三元环是 \(m \sqrt m\) 级别,复杂度 \(O(m\sqrt m)\),详见三元环计数。

另外,官方给出的复杂度证明为:

\(\sum_{v \in V}\min(deg(v)^2,m)\ \le \ \sum_{v \in V} \sqrt{deg(v)^2m} \ \le \ \sum_{v \in V}deg(v)\sqrt m = m \sqrt m\)

个人理解,每个点遍历的边数首先不超过 \(m\) 级别,而 \(u \rightarrow v,v \rightarrow w\) 的形式可视作 \(deg(v)^2\),所以每个点遍历的数量是两者取最小。

实现:

vector 存图会方便删除。

LGP3562 [POI2013] LAS-Laser

题意:

平面上有些线段,你最多从原点射出 \(k\) 条射线,穿过最多的线段,且使得每条线段最多被穿过 \(1\) 次。
求最多能穿过多少线段。

线段在第一象限。\(n \le 5\times 10^5,k\le 100\)

分析:

有一个小性质,选端点一定不比选中间差。可以自己画一画。

所以想到,把二维中的线段处理到一维上,即按每个点到原点连线的斜率找出它的排名 \(pos\),于是变成了一维选线段问题。记 \(cnt_i\) 表示第 \(i\) 个位置有几条线段,似乎可以 DP 了。

\(dp[i][j]\) 表示前 \(i\) 个端点里选了不超过 \(j\) 个端点的最大答案,发现若选择当前点,则前面的、被覆盖当前点的线段覆盖的点都不能选,因此对每个点,需要维护过该点的线段向左最多到哪,即 ”被 经过当前点的线段 覆盖的点“ 的最小坐标,记为 \(left_i\)

于是 \(dp[i][j]=max(dp[i-1][j],dp[lft[i]-1][j-1]+cnt[i])\)

发现空间开不下,于是把 \(j\) 的循环提到外层,\([0,1]\) 滚动即可。

实现:

for(int j=1;j<=k;j++)
{
    for(int i=1;i<=tot;i++)
    {
        if(lft[i]==inf)continue;
        dp[i][j&1]=max(dp[i-1][j&1],dp[lft[i]-1][(j-1)&1]+cnt[i]);
    }
}

2023.09.23

LGP1989 无向图三元环计数

题意:

求有向图中的三元环个数。

分析:

把无向边改成有向边,优先度数从小到大连边,度数相同按编号大小(小大大小选一种)连边。简单画画图可以发现,这样一定不会连出环(可以自己枚举一下成环的方式,会发现都不存在)。也即,三元环 \(u,v,w\) 会变成 \(u \rightarrow v \rightarrow w,u \rightarrow w\) 的形式。

于是遍历 \(u\) ,对每个 \(u\) 枚举 \(v\),对于每个 \(v\) 枚举 \(w\),一眼似乎是 \(O(m^2)\),然而其实是 \(O(m \sqrt m)\),证明如下。

\(deg(v)\) 表示度数,\(out(v)\) 表示出边数。

首先,可以认为枚举了每一条出边 \(e : u \rightarrow v\),并枚举了每个 \(v\) 的所有出边,所以复杂度式子为 \(\sum_{i=1}^m out(v)\)

考虑天然根号。一种是 \(out(v) \le deg(v) \le \sqrt m\),另一种 \(deg(v)>\sqrt m\),由于按度数从小到大连边,\(deg(w) \ge deg(v)\),所以 \(w\) 的数量不多于 \(\sqrt m\) 个。

综上, \(\forall v, \ out(v)\le sqrt(m)\),所以 \(\sum_{i=1}^m out(v) \le m \sqrt m\)

题目已经做完了,然而可以发现一个性质:每个三元环都被遍历过,而总复杂度不多于 \(m \sqrt m\),所以三元环数量不多于 \(m \sqrt m\)

性质应用见 LGP3547 [POI2013] CEN-Price List

实现:

似乎没什么细节。

2023.09.25

LGP3800 Power收集

题意:

略。

分析:

很板的单调队列优化 DP。

实现:

你 tm 能不能好好看看你往函数里传了啥。

建议是如果用了 \(i\)\(j\) 列的枚举,那在外层处理行相关时最好也写成 \(j\),不容易写错。

SP10707 COT2 - Count on a tree II

题意:

每次求树上 \(u,v\) 两点间结点的不同颜色数。

分析:

树上莫队板子。

实现:

2023.09.26

CF1000E We Need More Bosses

题意:

给定一个 \(n\) 个点 \(m\) 条边的无向图,保证图连通。找到两个点 \(s,t\),使得 \(s\)\(t\) 必须 经过的边最多(一条边无论走哪条路线都经过ta,这条边就是必须经过的边),\(2<=n<=3*10^5,1<=m<=3*10^5\)

分析:

赛时没一眼切,最开始写假,看了树的部分分得到启发,切掉了。

将图用点双缩点,在缩出来的树上求一个直径,结束。

2023.09.27

CF1795E Explosions?

题意:

有一排怪物,可以用单点或者爆炸攻击,单次伤害等于消耗。爆炸只能结尾用一次,爆炸伤害大于等于当前怪 \(hp_i\) 会向两侧扩散 \(hp_i-1\) 的伤害,求最小消耗。

分析:

赛时写了带剪枝暴力,甚至重造数据也没卡掉(当然 CF 肯定卡掉了)。赛时想过优化,补题时也想了,然而没弄明白。

正解是 DP,方法比较多样。

采用了 \(dp[0/1][i]\) 表示第 \(i\) 个点产生爆炸时,向左(右)最多造成多少伤害(包括自身),剩下的部分最后加一下,逻辑上视作提前点掉。

转移时,找到第一个 \(h_j\) 小于当前点的位置 \(j\),因为 \(j\) 会使爆炸伤害减小;中间部分等差数列求和。
式子比较繁琐,直接扔代码,等理解上升再回来看。

        while(!s.empty()&&f[s.top()]>=f[i])s.pop();
        int j=s.top();
        if(!j)
        {
            j=max(1,h[i]-i+1);
            dp[flag][i]=(1ll*h[i]+j) * (1ll*h[i]-j+1) /2;
        }
        else
        {
            dp[flag][i]=dp[flag][j] + (1ll*h[i]+h[i]-(i-j-1)) * (1ll*i-j) /2;
        }

反向转移需要改式子,然而没改明白,最终妥协,reverse 了事。

CF1794E Labeling the Tree with Distances

题意:

给你一个树,边权为 \(1\)。给定 \(n-1\) 个数,你需要将这些数分配到 \(n-1\) 个节点上。

一个点 \(x\) 是好的,当且仅当存在一种分配方案,所有被分配数的点到 \(x\) 的最短路径长度等于其被分配的数。

求所有好点。

这里设题目给出的数的集合为 \(A\),为方便表述,在其中添加一个数 \(0\)

分析:

一道哈希好题。

赛时只写了暴力。但是发现了此题的本质是维护以节点 \(i\) 为根时的 \(dep\) 集合 \(D\),并判断 \(D\) 是否包含 \(A\)。进一步地,可以理解为,\(D\) 是不是只与 \(A\) 有一项不同。

像这样快速处理集合的问题,很多可以用哈希维护。

在本题中,考虑将一个 \(dep_i=d\) 转成 \(base^d\),于是不同 \(dep\) 互不影响,相同 \(dep\) 可以相加减。在需要把子树集合并入当前集合时,逻辑上需要将其每一项加一,所以实际上将整体乘 \(base\) 即可,其它操作类似。

在判断时,只需将所得哈希值与给出值的哈希值相减:若仅 \(D\) 中一个 \(x\) 未匹配,所得一定为 \(base^x-0\),即底数的一个幂;反向依然成立。

LGP3585 [POI2015] PIE

题意:

一张 \(n\times m\) 的方格纸,有些格子需要印成黑色,剩下的格子需要保留白色。

一个 \(a\times b\) 的印章,有些格子是凸起(会沾上墨水)的。

印的过程中需要满足以下要求:

  1. 印章不可以旋转。
  2. 不能把墨水印到纸外面。
  3. 纸上的同一个格子不可以印多次。

判断能否用这个印章印出纸上的图案。

分析:

看题的时候读错题,想了半天。

比较简单的贪心:找到印章的最“左上”的位置(此处由于第一维按行遍历,行优先),则纸上没有印的最“左上”的点一定要由印章最“左上”的点印,每次判断印法是否合法。

注意需要存一下有用的点,否则会 TLE。

兄弟,结构体是真的好用,快加入结构体教吧。

2023.09.28

LGP3582 [POI2015] KIN

题意:

最大子段和,但是重复的值不计入贡献。

分析:

动态地从 \(1\)\(n\) 加入,每次把前面最近的相同权值的位置取负,再前面的改为 \(0\),以消除重复值带来的影响,线段树维护最大子段和。

实现:

线段树的 pushup 最好直接写成传引用的版本,否则大量左移操作可能会 T。

P3586 [POI2015] LOG

题意:

维护一个长度为 \(n\) 的序列,一开始都是 \(0\),支持以下两种操作:

  1. U k a 将序列中第 \(k\) 个数修改为 \(a\)
  2. Z c s 在这个序列上,每次选出 \(c\) 个正数,并将它们都减去 \(1\),询问能否进行 \(s\) 次操作。

每次询问独立。

分析:

可以用数馒头的方式,发现结论:若有 \(x\) 个大于等于 \(s\) 的数,只要剩下的数的和大于等于 \((c-x)\times s\) 就一定有解。平衡树维护。

实现:

似乎没什么细节。

2023.09.29

LGP3594 [POI2015] WIL

题意:

给定一个长度为 \(n\) 的序列,你有一次机会选中一段连续的长度不超过 \(d\) 的区间,将里面所有数字全部修改为 \(0\)。请找到最长的一段连续区间,使得该区间内所有数字之和不超过 \(p\)

分析:

第一思路二分长度,每次单调队列维护当前区间内可以删去的权值和的最大值。

事实上可以直接双指针扫(?),因为当 \(r\) 扩展到 \(r+1\) 时,左端点是不会再向左移动的(要是能的话在 \(r\) 就已经移动了)。

实现:

似乎没什么细节。

UVA1619 感觉不错 Feel Good

题意:

定义区间的权值为:权值和乘以最小值。求权值最大的区间。

分析:

比较板的单调栈,维护以每个点为最小值时区间向左右最多扩展到哪里。

实现:

暑假开始的时候写的,然而不知道怎么没调出来,这回可能是理解到了,直接过掉了。

2023.09.30

LGP3524 [POI2011] IMP-Party

题意:

给定一个 \(3n\) 个点 \(m\) 条边的图,保证存在 \(2n\) 的团,求一个 \(n\) 的团。

分析:

奇妙思维题。

可以考虑将至多 \(2n\) 个点删去,剩下的一定在团里,输出即可。

具体地,若两个点互不连通,则至少有一个不在团里,将两个点都删去,最多删 \(2n\) 个,还剩 \(n\) 个,不会有问题。

实现:

注意逻辑,别急。

一种很阴间的排版

LGP3522 [POI2011] TEM-Temperature

题意:

对每一天的天气都给出上界和下界,求最长可能有多少个连续天的温度不下降。

分析:

设最低温为 \(mn_i\),最高温为 \(mx_i\)

若以当前天为结尾,则只需所选区间内的最低 \(mn\) 均不高于当前天 \(mx\) 即可,换言之,限制只有前面一段的最小 \(mn\)

则考虑单调队列,在队尾弹出 \(mn\) 比新元素大的,队首弹出 \(mn\) 过大的点。

实现:

对于这种取一段区间的,可以维护下标计算区间长,也可以使用 \(cnt、size\) 的方式维护当前点“代表”了多长的区间。

P3528 [POI2011] PAT-Sticks

题意:

给你每根木棍的长度和颜色,求一个能拼成三角形且木棍颜色互不相同的方法。

分析:

神奇思维题。

由于三角形三边性质,若最长的木棍无法与次长、次次长拼出,则一定无法与其他所有拼出,于是可以丢掉。

所以每次选择不同色的三个最长,如果不可行就丢弃最长,直到有解或无解(无法选出同色或不到三条)。

实现:

每个颜色建堆维护最长,再用另一个堆维护每个颜色最长木棍,模拟即可。

P3529 [POI2011] PRO-Programming Contest

题意:

\(n\) 个人 \(m\) 个题目,每个题要 \(r\) 分钟完成。比赛有 \(t\) 分钟。给出每个人会做哪些题目,请你安排一个每个人在什么时候做什么题目,使得做出来的题目数最多。在做题数一样多的情况下,罚时尽量小。

分析:

显然二分图最大匹配,然而罚时不好搞。

经典方法之动态加边。

每次只给每人加 \(1\) 的流量,当无法继续做题时结束。

实现:

哪个 shaber tot 不赋 1 调了三天我不说。

建议修改边权而不是新建边,不知道新建的话空间够不够。

posted @ 2023-10-15 17:47  浣熊’  阅读(58)  评论(0)    收藏  举报