CF data structure 自制题单(一)

CF data structure 2000~2100

为你的战斗,献上雷鸣般的喝彩!——唔姆

目标 30 道题

1. Problem - 1555E - Codeforces

看了提示
给一些线段,每个现段有 l , r , w l, r, w l,r,w 三个属性。现在要求选出一个集合,使得集合中的线段的并覆盖区间 [ 1 , m ] [1, m] [1,m],并且线段的权值之和最小.

按照现段的权值排序,然后发现有单调性。对排好序的线段数组,固定好右端点 r r r 后,只要有一个左端点 l 0 l_0 l0 满足 [ l 0 , r ] [l_0,r] [l0,r] 之间的现段的并可以覆盖 [ 1 , m ] [1,m] [1,m],那么对于 l < l 0 l < l_0 l<l0,都会满足 [ l , r ] [l,r] [l,r] 线段并覆盖 [ l , r ] [l,r] [l,r].

然后维护一个线段的并就可以了. 这个可以使用 “矩阵的并” 那个扫描线算法。无需懒标记.

2. Problem - 1536D - Codeforces

给一个序列 b 1 , b 2 , . . . , b n b_1, b_2,...,b_n b1,b2,...,bn,问能否找到一个序列 a a a,使得对于每一个 b i b_i bi b i b_i bi a 1 , a 2 , . . . , a 2 i − 1 a_1,a_2,...,a_{2i-1} a1,a2,...,a2i1 的中位数。这里的中位数指的是排完序之后的中间的那个数字.

我们模拟一下发现,这样子可以构造出来。设 m i d mid mid 为当前的中位数, p p p m i d mid mid 前面那个数字, q q q m i d mid mid 后面那个数字.

如果 b i < p b_i < p bi<p b i > q b_i > q bi>q,那么输出 NO
如果 b i = m i d b_i = mid bi=mid,那么往里面塞一个 − ∞ -\infty + ∞ +\infty + 进去就行了.
如果 b i = p b_i = p bi=p,那么塞两个 − ∞ -\infty
如果 b i = q b_i = q bi=q,那么塞两个 + ∞ +\infty +
否则,塞一个 b i b_i bi,根据 b i b_i bi m i d mid mid 的大小看塞 − ∞ -\infty 还是 + ∞ +\infty +

3. Problem - 1525C - Codeforces

n ( n ≤ 3 × 1 0 5 ) n(n \le 3 \times10^5) n(n3×105) 个机器人在 [ 0 , m ] [0,m] [0,m] 之间走动,碰到墙壁就会原路返回。两个机器人在整数点碰撞爆炸消失,但是在非整数点碰撞没有事情。问每个机器人的爆炸时间.

这种碰撞题,想办法用一个链表和优先队列就可以了.

由于只能在整数点相撞。因此只有奇偶性相同的时候才可能碰撞。因此分开求。

然后,就用一个优先队列,把相邻的两个加入到优先队列中,然后弄一个双链表维护一下左右两边相邻的机器人是哪个.

4. Problem - 1516D - Codeforces

给一个长度为 n n n 的序列, 1 ≤ n ≤ 1 0 5 1\le n \le 10^5 1n105 1 ≤ a i ≤ 1 0 5 1 \le a_i \le 10^5 1ai105 , q ( q ≤ 1 0 5 ) q(q\le 10^5) q(q105) 组询问,问可以最少把它们分成多少连续子区间,使得每个子区间内的 l c m lcm lcm 为区间内数字的乘积.

我们发现只有区间内数字两两互质的时候才可能满足此条件. 记录一个 R R R 链表,初始化 R [ i ] = n + 1 R[i] = n + 1 R[i]=n+1。 因此我们对于每一个点看看最往右的与它不互质的数字是哪一个。然后对于每个质数处理一下就可以了.

最后就建立了一个往后跳的链表。现在问题就变成了 l l l 跳多少次可以到达大于 r r r 的位置。这个可以用倍增法来求.

5. Problem - 1493D - Codeforces

给了 n n n 个数字,给了 q q q 次操作,每次将 a i a_i ai​ 乘以 x x x,在每次操作后输出整个数列的 g c d gcd gcd

把数列分解质因数, x x x 分解质因数,然后看每个质因数的变化情况即可. 最大公因数取决于所有数字的某个质因数的最小幂次. 不要漏掉 0 0 0 次幂这个东西.

6. Problem - 1487E - Codeforces

有四个集合,集合中每个数字有权重,集合大小分别是 n 1 , n 2 , n 3 , n 4 n_1, n_2, n_3, n_4 n1,n2,n3,n4,第一个集合和第二个集合之间有 m 1 m_1 m1 对儿数字不可以同时,同理第二个集合和第三个集合有 m 2 m_2 m2 对儿数字不可以同时存在,第三个集合和第四个集合有 m 3 m_3 m3 对儿数字不可以同时存在。现在从四个集合中各选一个数字,求数字权重之和最小是多少.

我们会发现集合之间的限制,两两独立。即我们只需要先计算出 1 1 1 2 2 2 两个集合之间的限制,然后用这个答案去更新 2 2 2 3 3 3 之间的限制,依次类推。比如对于第二个集合,计算每一个数字和第一个集合那个数字匹配,权重之和是最小的. 这个排一下序暴力查找就可以了.

7. Problem - 1486D - Codeforces

不会写
给一个长度为 n n n 的序列,求长度至少为 k k k 的连续子区间的中位数最大是多少。中位数这里定义为排好序之后的位于 ⌊ n + 1 2 ⌋ \lfloor \dfrac{n + 1}{2} \rfloor 2n+1 的数字.

首先,可以二分答案. 然后让大等于 x x x 的数字置为 1 1 1,小于 x x x 的数字置为 − 1 -1 1,然后打一个前缀和,对于每一个 i i i,在 j = 0 , 1 , 2 , . . . , i − k j = 0,1,2,...,i-k j=0,1,2,...,ik 中找到 s u m [ j ] sum[j] sum[j] 的最小值,看 s u m [ i ] − s u m [ j ] sum[i] - sum[j] sum[i]sum[j] 是否大于0.

8. Problem - 1482E - Codeforces

n n n 个楼房,每个楼房有一个高度 h i h_i hi 和一个美丽值 b i b_i bi,现在要求把序列划分为几个连续子段,每个子段的美丽值是最低的楼房的高度的美丽值。这个序列的美丽值是子段美丽值之和. 求此序列的美丽值的最大值.

d p i dp_i dpi 为第 1 ∼ i 1 \sim i 1i 的最佳划分. 那么我们用一个单调栈,找到左边第一个小于 h i h_i hi 的楼房是哪个,设为 k k k. 于是就讨论 i i i 是否要和 k k k 一组,如果一组的话就是 d p i = d p k dp_i = dp_k dpi=dpk,如果不一组的话就是 max ⁡ k ≤ j ≤ i − 1 d p j + b i \max\limits_{k \le j \le i - 1}dp_j + b_i kji1maxdpj+bi.

9. Problem - 1479B2 - Codeforces

不会写
把一个序列划分为两个子序列,相同且相邻的元素可以合并为同一个. 问两个序列最后最少共可以剩下多少元素?

f ( i . j ) f(i. j) f(i.j) 表示处理完 a i a_i ai,另一组数字是 j j j 的划分最小值.

f ( i , j ) = f ( i − 1 , j ) + [ a i − 1 ≠ a i ] f ( i , a i − 1 ) = f ( i − 1 , j ) + [ a i ≠ j ] f(i,j) = f(i - 1, j) + [a_{i-1} \ne a_i] \\ f(i, a_{i-1}) = f(i - 1, j) + [a_i \ne j] f(i,j)=f(i1,j)+[ai1=ai]f(i,ai1)=f(i1,j)+[ai=j]

10. Problem - 1446C - Codeforces

n n n 个不同的数字,对于每个数字 a i a_i ai,找到 i ≠ j i \ne j i=j 使得 b i ⊕ b j b_i \oplus b_j bibj 最小. 然后在 i i i j j j 之间连一条边。最后会形成一个森林。现在让删掉尽可能少的结点,使得最后的数组可以形成一棵树.

建立字典树出来,一个点与另一个点的之间右边,那么它们最近公共祖先的高度一定是最低的. 然后深搜一下, c n t p = max ⁡ { c n t p . l , c n t p . r } + 1 cnt_p = \max\{cnt_{p.l},cnt_{p.r}\} + 1 cntp=max{cntp.l,cntp.r}+1. 相当于节点少的子树只保留一个点. 子树为空的时候特判.

11. Problem - 1420C2 - Codeforces

不会写

给一个 1 ∼ n 1 \sim n 1n 的随机排列 a a a,要求选出一个子序列 [ b 1 , b 2 , . . . , b k ] [b_1, b_2, ..., b_k] [b1,b2,...,bk] 出来,这个子序列的值就是 b 1 − b 2 + b 3 − b 4 . . . b_1 - b_2 + b_3 - b_4... b1b2+b3b4.... 现在给 q q q 个操作, l , r l,r l,r,每次交换 a [ l ] , a [ r ] a[l],a[r] a[l],a[r],求每次交换后子序列的最大值是多少.

定义极大值点为 a i > a i − 1 a_i > a_{i - 1} ai>ai1 a i > a i + 1 a_i > a_{i + 1} ai>ai+1;定义极小值点为 a i < a i − 1 a_i < a_{i - 1} ai<ai1 a i < a i + 1 a_i < a_{i + 1} ai<ai+1. 那么答案就是极大值之和减去极小值之和. 并且第 1 1 1 个数字和第 n n n 个数字一定不是极小值.

发现这个,这个题就很简单了。因为每次操作,会改变状态的数字不超过 6 6 6 个.

12. Problem - 1418D - Codeforces

初始有 n n n 堆垃圾散落在x轴上,你需要把垃圾收集到至多两个点上。每次你可以把处于 i i i 位置的垃圾,全部扫到 i − 1 i-1 i1 或者 i + 1 i+1 i+1 的位置上。问至少需要几次操作才能完成任务。之后有人捣乱 q q q 次,每次会在一个位置上制造出一堆垃圾,或者清理掉这堆垃圾。每次捣乱后需要分别求出答案。

相当于找到垃圾的最大值 m a x x maxx maxx,最小值 m i n x minx minx,以及排好序最大的差分 m a x d maxd maxd,答案就是 m a x x − m i n x − m a x d maxx - minx - maxd maxxminxmaxd.

multiset 就可以实现,思路很简单,不过细节较多,注意特判.

13. Problem - 1416C - Codeforces

n n n 个数字的序列 a a a,然后找到一个最小的数字 x x x,有 b i = a i ⊕ x b_i = a_i \oplus x bi=aix,使得 b b b 序列的逆序对最少.

画出字典树就看出来了,如果 x x x 的第 i i i 为填 1 1 1,相当于把第 i i i 层的左右子树交换,然后看看逆序对。并且交换子树,对上层的结点之间的逆序对是不会有影响的,即每一层之间交换子树对答案的贡献都是独立的.

14. Problem - 1408D - Codeforces

不会写

n ( n ≤ 2000 ) n(n \le 2000) n(n2000) 个机器人, m ( m ≤ 2000 ) m(m \le 2000) m(m2000) 个照明灯。所有坐标的范围都是 [ 1 , 1 0 6 ] [1,10^6] [1,106]. 一个机器人 ( x i , y i ) (x_i,y_i) (xi,yi) 被一个照明灯找到,当且仅当 x i ≤ x j x_i \le x_j xixj y i ≤ y j y_i \le y_j yiyj. 现在让所有机器人的 x x x 同一个数 a a a,让 y y y 增加同一个数 b b b,使得所有机器人都不能被照明灯找到,问 a + b a+b a+b 的最小值是多少.

我们观察,对于 ( i , j ) (i,j) (i,j),必须要满足 a + x i > x j a+x_i >x_j a+xi>xj b + y i > y j b+y_i > y_j b+yi>yj. 假如 a ≤ x j − x i a \le x_j - x_i axjxi,那么 b ≥ y j − y i + 1 b \ge y_j - y_i + 1 byjyi+1. 那么可以从 0 0 0 1 0 6 10^6 106 枚举 a a a,看看所有 a ≤ x j − x i a \le x_j - x_i axjxi 之中, y j − y i + 1 y_j - y_i + 1 yjyi+1 的最小值是多少。然后更新答案。

15. Problem - 1388D - Codeforces

给长度为 n n n 的序列 a , b a,b a,b. 初始时 a n s = 0 ans = 0 ans=0. 每次操作可以选择一个之前没有选过的下标 i d id id,然后 a n s + = a i d ans += a_{id} ans+=aid, a i d + = a b i d a_{id}+=a_{b_{id}} aid+=abid. 现在让这个 a n s ans ans 最大,输出这个最大值和方案. 保证 b b b 形成的是一个森林(即无环)

我们先考虑如果 b b b 形成的是一条链,很简单的贪心策略,就是从前往后扫描,如果前缀和变成了负数,就截断。下面的序列便是新的起点,然后接着扫描. 树的话一样的写法.

输出的话要倒序输出.

16. Problem - 1379C - Codeforces

不会写

m m m 种类型的花,每种花可以挑任意数量. 每种花有两个参数 a , b a,b a,b,如果这种花买了 x x x 支,则得到的美丽值就是 a + b ∗ ( x − 1 ) a + b*(x - 1) a+b(x1). 问最后挑选 n n n 朵花能够得到的美丽值之和的最大值.

可以这么考虑,最后应该是一支花一直选择下去。不妨假设这种花的参数是 a i , b i a_i,b_i ai,bi. 那么可以发现,如果存在 j j j,有 b j > b i b_j > b_i bj>bi,那不如换成这种花一直选。如果 b j = b i b_j = b_i bj=bi,那么就选择 a i a_i ai a j a_j aj 的较大值去选. 如果 b j < b i b_j < b_i bj<bi,那么选择一个 b j b_j bj 不如选择一个 b i b_i bi. 因此就会发现一个问题,只有一种花会选择超过1支,其他的花,要么不选,要么之选一支。选的话就只选 a j > b i a_j > b_i aj>bi 的花. 这样子,就好搜索了.

17. Problem - 1370E - Codeforces

给两个字符串 s , t s,t s,t,只有 0 0 0 1 1 1 组成,然后每次可以挑选 s s s 的一个子序列,做一次旋转,即 c 1 : = c k , c 2 : = c 1 , c 3 : = c 2 , … , c k : = c k − 1 c_1:=c_k, c_2:=c_1, c_3:=c_2, \ldots, c_k:=c_{k-1} c1:=ck,c2:=c1,c3:=c2,,ck:=ck1. 问最少需要操作几次,就可以让 s s s 变为 t t t. 字符串长度 n ≤ 1 0 6 n \le 10^6 n106.

s i = t i s_i = t_i si=ti 的时候,可以自动忽略。然后就是,可以认为每次操作都是对一个 101010... 101010... 101010... 或者是 010101... 010101... 010101... 操作. 于是统计 0 0 0 的个数和 1 1 1 的个数,记作 c n t 0 cnt_0 cnt0 c n t 1 cnt_1 cnt1. 记录 c n t 0 − c n t 1 cnt_0 - cnt_1 cnt0cnt1 的最大值是多少,以及最小值是多少,两者之差就是答案。

c n t 0 − c n t 1 cnt_0-cnt_1 cnt0cnt1 为正的时候,是第一种操作 101010... 101010... 101010...;为负的时候是第二种操作 010101... 010101... 010101.... 然后 c n t 0 − c n t 1 cnt_0-cnt1 cnt0cnt1 相同的位置都可以划到同一次操作里面.

18. Problem - 1359D - Codeforces

看了提示

给一个长度为 n ( n ≤ 1 0 5 ) n(n \le 10^5) n(n105) 的序列 a ( − 30 ≤ a i ≤ 30 ) a(-30 \le a_i \le 30) a(30ai30),找到一个连续子序列,使得 子序列的和减去该子序列的最大值 最大。

对于每个值,向左向右找到第一个严格大于它的数,然后在左边子区间中找到最小前缀和的值,在右边区间中找到最大前缀和的值. 相减即可.

19. Problem - 1322B - Codeforces

不会写

给一个长度为 n n n 的序列 a a a n ≤ 4 × 1 0 5 , 1 ≤ a i ≤ 1 0 7 n \le 4 \times 10^5, 1 \le a_i \le 10^7 n4×105,1ai107. 求
( a 1 + a 2 ) ⊕ ( a 1 + a 3 ) ⊕ … ⊕ ( a 1 + a n ) ⊕ ( a 2 + a 3 ) ⊕ … ⊕ ( a 2 + a n ) … ⊕ ( a n − 1 + a n ) (a_1 + a_2) \oplus (a_1 + a_3) \oplus \ldots \oplus (a_1 + a_n) \\ \oplus (a_2 + a_3) \oplus \ldots \oplus (a_2 + a_n) \\ \ldots \\ \oplus (a_{n-1} + a_n) (a1+a2)(a1+a3)(a1+an)(a2+a3)(a2+an)(an1+an)

可以对答案每一位来考虑。数位从 0 0 0 开始编号,对于答案第 k k k 位,只需要关心原数组的 0 ∼ k 0 \sim k 0k 位,因此可以把所有数字模 2 k + 1 2^{k+1} 2k+1. 然后两个数字之和的范围就是 [ 0 , 2 k + 2 − 2 ] [0, 2^{k+2}-2] [0,2k+22]. 容易分析,当两数之和在 [ 2 k , 2 k + 1 − 1 ] ∪ [ 2 k + 1 + 2 k , 2 k + 2 − 2 ] [2^k, 2^{k+1}-1] \cup [2^{k+1}+2^k,2^{k+2} - 2] [2k,2k+11][2k+1+2k,2k+22] 的时候才可以。然后就可以用双指针计算答案了.

20. Problem - 1320C - Codeforces

n n n 把剑 m m m 个盾,每个剑有攻击值每个盾用防护值,剑和盾都有花费。有 p p p 个怪,每个怪有攻击力和防御力。打败一个怪需要你的剑的攻击值严格大于怪的防御力,你的盾的防御值严格大于怪的攻击力。打败一个怪可以获得对应的收益。你只能买一把剑和一个盾。求打败所有能打的怪后最大的收益,可能为负。
1 ≤ n , m , p ≤ 2 × 1 0 5 1 \le n, m, p \le 2 \times 10^5 1n,m,p2×105.

相当于二维数点的问题. 把怪物攻击防御两个属性当作平面上的点. 然后枚举剑,把小于剑攻击力的怪物加进来,然后找的是每个盾能防御的怪减去盾的费用 的最大值. 后者用线段树维护就好.

小心用 upper_bound 查询 pair 的时候,要写成 int l = std::upper_bound(b + 1, b + m + 1, std::mp(c[id].y, (int)1e9+5)) - b;

21. Problem - 1304E - Codeforces

n   ( n ≤ 1 0 5 ) n\ (n \le 10^5) n (n105) 个结点的树,然后给 q q q 个询问,每次询问在树上 x , y x, y x,y 两点间加一条额外的边形成基环树,然后问两个点 a , b a, b a,b 之间是否存在一条路径,其长度恰好为 k k k. 路径可以有重复的边和点.

很经典的基环树题目, 也就是讨论一下是否走 ( x , y ) (x, y) (x,y) 这条边: d i s t ( a , b ) ≤ k dist(a, b) \le k dist(a,b)k 并且奇偶性一致; d i s t ( a , x ) + d i s t ( b , y ) + 1 ≤ k dist(a, x) + dist(b, y) + 1 \le k dist(a,x)+dist(b,y)+1k 且奇偶性一致; d i s t ( a , y ) + d i s t ( b , x ) + 1 ≤ k dist(a, y) + dist(b, x) + 1 \le k dist(a,y)+dist(b,x)+1k 且奇偶性一致。三个条件满足其一即可.

22. Problem - 1299C - Codeforces

看了提示

n n n 个数字,每次可以选择一个区间,将区间内的所有数字变成区间数字的平均值。求所得字典序最小的序列。

比较经典的问题了。区间划分然后全部变成平均值之类的。首先我们发现区间不会有相交的情况。然后就是用一个单调栈,维护一段一段的区间。如果当前段的均值比上一个的小,就与上一个合并,否则就作为一个新的区间段存入单调栈中.

23. Problem - 1288E - Codeforces

给一个 1 ∼ n   ( n ≤ 3 × 1 0 5 ) 1 \sim n\ (n \le 3 \times 10^5) 1n (n3×105) 的排列,给 m   ( m ≤ 3 × 1 0 5 ) m\ (m \le 3 \times 10^5) m (m3×105) 个询问,每次给一个数字 x x x,把 x x x 丢到数组最前面去. 最后问每个数字出现位置的最大值和最小值.

本来打算用一个平衡树加上懒标记啥的. 其实根本不用那么复杂. 用一个树状数组,最开始把数字放在 m + 1 ∼ m + n m + 1 \sim m + n m+1m+n 的位置,树状数组那些位置置为1,然后把第 i i i 询问的数字位置的数字置为0,然后把第 m − i m - i mi 位置的数字置为1. 这样就模拟出来了过程.

24. Problem - 1284D - Codeforces

很简单的一道题却调了很久
n n n 个演讲,每个演讲如果在 A A A 举办,举办时间是 [ s a i , t a i ] [sa_i, ta_i] [sai,tai]. 若在 B B B 举办,举办时间是 [ s b i , t b i ] [sb_i,tb_i] [sbi,tbi]. 现在假设演讲全在一个地方举办,问能否选出一个集合出来,使得在一个地点两两有交集,在另一个地点两两没有交集.

首先可以确定只需要看两个区间就可以了. 我的做法是在 A A A 地两两有交集的区间里面,看在 B B B 举办的时候是否存在两个不相交的情况. 如果存在,那么答案就是 NO,都不存在就是 YES. 前半部分用一个扫描线即可,把左端点置为 -1 右端点置为 1. 后半部分可以用两个 multiset. 加入一个新区间的时候,要想判断这个区间和其他区间有无交集,可以看其左端点是否大于集合中右端点最大值,以及右端点是否小于集合中左端点最小值.

25. Problem - 1278D - Codeforces

n   ( n ≤ 5 × 1 0 5 ) n\ (n \le 5 \times 10^5) n (n5×105) 个区间,保证端点都不相同,对于区间 i , j i,j i,j,如果两个区间有交集并且两个区间并非包含关系,那么 i i i j j j 之间连一条边. 问最后形成的是否是一棵树.

还是可以转化成二维数点的问题. 对于每一个点,其左下方的点一定和他有交集。然后在这些点中,找到 r r r 大于当前节点的左端点的值的那些点,连边即可.

用一个权值线段树就行了.

26. Problem - 1271D - Codeforces

题意较为复杂:要攻取 n n n 个城市(不能漏),一开始有 k k k 个兵,攻取第 i i i 个城市需要 a i a_i ai 个兵,攻取之后可以获得 b i b_i bi 个士兵,如果有一个人在这里防守可以获得 c i c_i ci 的分数. 要么攻取之后留下一人守卫,要么攻取到后面的城市后把一名士兵通过道路 ( m ≤ 3 × 1 0 5 m \le 3 \times 10^5 m3×105)派回来守卫. 问最大分数是多少。

首先把所有能够攻占后并达到的城市存入优先队列中,首先处理出来有哪些城市可以通过那个城市派兵到达. 加入现在在第 i i i 个城市,从 i i i 往后仍然可以继续进攻的条件是 ∑ j = 0 i − 1 b j ≥ a i \sum\limits_{j=0}^{i-1}b_j \ge a_i j=0i1bjai i i i 后面的城市都要满足这个条件。所以可以用一个线段树维护一下最小值. b 0 = k b_0 = k b0=k.

27. Problem - 1266E - Codeforces

有点难,还没想出来怎么写
n n n 种物品需要生产,第 i i i 种物品需要 a i a_i ai 个。现在有一些魔法石,有三个参数 ( s j , t j , u j ) (s_j, t_j , u_j) (sj,tj,uj). 表示如果现在有 t j t_j tj s j s_j sj,那么会自动生成一个 u j u_j uj. 现在给 q q q 个操作,每次都会新增、删除或修改一个魔法石,问每次需要产生所有物品至少需要自己生产.

28. Problem - 1266D - Codeforces

看了一点提示

d ( a , b ) d(a, b) d(a,b) a a a b b b 的钱数. 如果有 d ( a , b ) , d ( c , d ) d(a, b), d(c,d) d(a,b),d(c,d),可以把 d ( a , b ) , d ( c , d ) d(a, b),d(c,d) d(a,b),d(c,d) 同时减少 z z z,
d ( a , d ) , d ( c , b ) d(a,d), d(c,b) d(a,d),d(c,b) 同时增加 z z z;还有就是如果 d ( a , a ) > 0 d(a,a) > 0 d(a,a)>0,可以让 d ( a , a ) d(a, a) d(a,a) 等于0. 求最后可以使得总和最少. 求最少总和的情况下对应的债务关系.

我发现 d ( a , b ) , d ( b , c ) d(a, b), d(b, c) d(a,b),d(b,c) 存在的情况下可以减少总和,并且使债务关系不会变多. 因此我们可以围绕 b 做处理,每次可以消去一个 d ( a , b ) d(a, b) d(a,b) 或者 d ( b , c ) d(b, c) d(b,c),增加一个 d ( a , c ) d(a, c) d(a,c). 因此只要处理完 b b b 之后,就不用在管他了。
但是直接模拟一遍会超时,第 84 个测试会卡掉. 因此可以换种思考方式,统计每个人的收入和支出,并且进行抵消. 然后把收入为正和为负的分为两部分,收入为正的人接受收入为负的人的贷款,用这个构造答案即可.

29. Problem - 1263E - Codeforces

给一个随时可以修改的包含左右括号的括号串,问当前括号串是否合法,以及左括号的最大深度是多少.

这个题只需要记录一个左括号前缀和与右括号前缀和的差值,维护一下这个差值的全局最大值和最小值即可. 这个可以线段树去做. 比较简单的一道题.

30. Problem - 785E - Codeforces

不会写
给一个 1 ∼ n   ( n ≤ 1 0 5 ) 1 \sim n \ (n \le 10^5) 1n (n105) 的排列,给 q   ( q ≤ 50000 ) q\ (q \le5 0000) q (q50000) 组操作,每次交换 l , r l, r l,r 两个位置的数字。问每次交换之后的逆序对是多少.

其实统计的就是 l ∼ r l \sim r lr 之间的数字,有多少个是位于 a l a_l al a r a_r ar 之间的. 这个其实很简单的,分块,每块内部维护一个升序的 vector,这样子的话,在 l , r l,r l,r 所在的块内部暴力修改与查询,中间的块不涉及修改操作,因此二分查找即可.

你可能感兴趣的:(ACM题目整理,算法,数据结构)