复盘|第338场周赛
K 件物品的最大和
【模拟】 按照1,0,-1的顺序选前k个。
【分类讨论】如果k <= numOnes + numZeros,ans=前k里面1的数量,剩下情况,只能选numsOnes - (k - numOnes - numZeros)即ans=前k里面1的数量减-1的数量。
质数减法运算
前置知识:埃式筛又称素数筛,从2开始将每个素数的倍数都标记成合数;线性筛是对埃式筛的优化,在筛选每个合数时,用它的最小质因子去筛。
【埃式筛 + 二分】因为要严格递增,所以前面的数要尽可能小,首先nums[0]减去小于nums[0]的最大质数,然后对于每个num, 因为严格递增,所以num - prime > pre,移项prime < num - pre。代码中,primes里初始放一个0作为哨兵,避免二分越界。
数据范围较大时可以换成线性筛。
使数组元素全部相等的最少操作次数
【排序 + 前缀和 + 二分】由于每次只能加减1,所以就是每个元素到q的距离,要求的距离和相当于矩形面积减掉前缀和。
收集树中金币
【拓扑排序】首先跑一次拓扑排序删掉所有没金币的节点(”瘦身“)。再跑两次拓扑排序(DFS),去掉两轮叶子节点(含金币的叶子节点距离≤2即可,无需访问,删掉),得到了一颗”核心树“,其中每个节点都必须要访问。从树的任意节点出发,访问所有节点然后返回,每条边恰好访问两次。(以树上任意一点为根的欧拉回路长度都是边数×2,先删掉叶节点为0的边,使得每个树叶都为1,再删两层边,答案就是剩下的边数×2。)
代码中,用一个数组time记录每个点的入队时间(删掉叶子的时间),那么只要走到time[x]=2的节点x,就能收集到在叶子上的金币。遍历所有边x-y,如果满足time[x]≥2且time[y]≥2,那么这条边需要恰好经过2次(因为需要回到出发点),答案加2;如果不满足,则无需经过。