【刷(shui)题记录】201801末~201802上旬

在QBXT没有怎么刷过题,事实上就算刷了也因为硬盘损坏没有保存下来。发现自己与省队选手的差距还是有点大,从做题量上就已经有本质的区别。因此从1月末开始,记录一下每天的刷题吧。
说实话寒假作业有点多,努力权衡一下OI和文化课吧。

1.26

BZOJ4714——Math——Inclusion_Exclusion
考虑容斥原理,强制存在一个循环节的大小为 k 的方案数, 减去强制两个循环节大小为 k 的方案数, 加上强制存在三个循环节大小为 k 的方案数 我们只需要计算强制存在 t 个循环节,大小为 k 的方案数即可。

BZOJ3779——Data_Structure——LCT
实际上,如果你把release看成access,recenter看成makeroot,这就是一个LCT。
答案是什么?每个点的感染时间就是该点到根路径上虚边的个数。
所以只需要在access的时候维护子树的点权和即可。这个可以用DFS序+树状数组区间修改区间查询。
至于换根操作可以利用DFS序的性质分类讨论。(据说可以参考【BZOJ3083遥远的国度】)

BZOJ4715——DP——About_Map
因为选出来的序列是独立集,所以这个序列是递增的;又因为这是覆盖集,所以每个不在序列中的点都与某个序列中的点形成逆序对。所以我们求的就是还原序列后,极长上升序列的方案数。

1.27

BZOJ2716——Divide_Conquer——CDQ
CDQ分治,分类讨论拆绝对值的方式,分别查询最优值。
第一次写写了个75s的东西出来也是醉了。

BZOJ1014——Data_Structure——Splay
用splay维护字符串哈希,还TLE了一发,这天写的TLE十分多。

BZOJ3900——DP——Compression_DP
看数据范围显然是状压,思路是:发现答案最多为n-1,如果当i和j两个交换了角,我们就将i和j连边。
那么这样答案一定是一棵树或多棵树。考虑每个状态下最优情况即可。

1.28

BZOJ3065——Divide_Conquer——Block_in_Block
一般人都用替罪羊树之类的,我们比较暴力用分块套分块,而且跑得比那些数据结构快多了。
每个块在内部用“权值分块”的方法,记录每个数出现了多少次。
这个分块后的信息要做前缀和,也就是每一个块实际记录的是这个块和之前的总和。查询二分即可。

BZOJ2876——Math——Lagrange_Mult
二分+拉格朗日乘数法,基本上是学过就会做了。(但我的精度挂了一发~)

1.31

BZOJ3262——Divide_Conquer——CDQ
三维偏序经典题,注意去重。

BZOJ3589——Data_Structure——Heavy_Light_Cut
支持子树修改和链的并的查询,树链剖分。
对于查询考虑虚树或容斥原理即可。因为是对2^31取模,可以自然溢出。

BZOJ4002——Math——Matrix_Mult
构造数列 a n = b a n 1 + d b 2 4 a n 2
其中 a 0 = 2 , a 1 = b
然后我们求出这个数列的通项公式,得到 a n = ( b + d 2 ) n + ( b d 2 ) n
因此得到 ( b + d 2 ) n = a n ( b d 2 ) n
由于 b mod 2 = 1 , d mod 4 = 1 ,因此 d b 2 4 一定是个正整数,故我们可以利用矩阵乘法来求出这个数列的第 n

2.1

BZOJ4003——Data_Structure——Merge_Heap
对于一个节点上的全部骑士,只需要比较最菜的那个就行了。
同时攻占一个城池后的buff不会改变骑士的战力,打个标记即可。
这样我们可以用堆来维护。因为要从叶子节点往上进行合并,写个左偏树什么的。

BZOJ4004——Math——Linear_Basis
按价值从小到大排序,动态维护线性基,贪心购买装备。
这题的精度是坑,要用long double而且eps=1e-8才过。eps=1e-10时果断WA。

BZOJ4005——Math——Combinatorial
思维转化很神啊,想了2h+,自己的数学功底还是菜。
转化后发现是上(上)星期QBXT讲过的,虽然我没听懂,记得是关于折叠的就手推一发出来了。
详情见题解

BZOJ4006——DP——Steiner_Tree
这个图有特殊点这个东西,而且特殊点很少,可以想到斯坦纳树。
但是由于最后图的链接可能不是树,而是森林,所以我们要对最后的答案再枚举子集dp。

BZOJ4007——DP——Compression_DP
对于每个点,如果它到根的状态是确定的,那么它的左右子树的答案是独立的。
那么我们考虑dfs来状压,如果当前搜到的是叶子节点,我们可以 O ( n ) 扫一遍得答案,否则直接更新。

把JLOI2015做完了呢。

2.2

BZOJ2115——Math——Linear_Basis
考虑答案形式一定是一条路径+若干环。我们先求出1~n的任意一条路径。
此时我们会发现,1~n的其他路径可以通过这个路径异或某些环得到。这个东西在QBXT也讲过。
问题转化为有一个数和一个数集,使得这个数异或数集里的一些数后值最大,线性基做即可。

BZOJ3215——DP——Common
两两点之前的方案数是非独立的,所以求出两两点之间的方案数相乘就好了。
因为题目说的极小值(注意是极小值)均为0,所以每条斜率为-1的直线一定会到x轴再变成斜率为1的直线。
然后两点之间的方案数大概是和 2 k 有关,注意细节dp一下就行了。(这题BZOJ没题面没数据范围,洛谷有题面无范围,不过数组开1e6够了,2的幂用快速幂)

BZOJ4057——DP——Compression
范围显然状压,1表示破产,0表示未破产,最后就是统计有多少个只有一个0的状态可以到达。
考虑转移我们可以枚举先今存活的公司,统计他当前的债务情况,如果可以破产,那么就让它破产的状态为真,每次对可达到的状态进行以上操作即可。

BZOJ4058——Divide_Conquer——Common
观察后发现,当n为偶数时,只有全部数字都为0才能使得最后序列为0.
同时发现奇偶位数是独立的,所以分治判断即可。

BZOJ4059——Divide_Conquer——Common
一眼看到是暴力,不过想着复杂度好像不太对。敲了一发过了qwq。
预处理出每个元素左边和右边最近的相同元素的位置。
考虑一段序列[l,r],假如我们找到了序列中唯一元素的位置p 那我们只需检查[l,p-1]和[p+1,r]是否non-boring即可
注意,检查一段序列时我们应该从两头往中间找,可以证明复杂度是 O ( n l o g n ) 的,详细看这里

BZOJ4063——Simulation——Common
按题意模拟即可。(我写这题的原因就是快睡觉了,当然也是CERC2012的计划中的题)

2.3

BZOJ4060——DP——About_Map
首先显然这是一个拓扑图,我们只需要标号dp就行了。
难点在于字符串处理,建一棵Trie来做,在dp的边界时暴力处理。
字符串处理看着std打WA了无数发(还是用虚拟机来测试的)
后来发现想多了,我们可以贪心算出每个字符串从P的第i位开始匹配最远不能到达的下一个位置是谁,
如果这个字符串是两个字符串拼接而成,那么就是从左边串匹配完的位置继续在右边匹配得到的位置,记忆化搜索即可。
这个匹配直接Hash就行了。

BZOJ4061——Map——Dijkstra
这题主要难点在于距离的转化,详见题解

BZOJ4062——Others——Scan_Lines
一个比较直接的想法就是将颜色一个一个丢掉。
对于某个颜色的某个点,我们丢掉了,那么要将同颜色的所有点丢掉。
考虑扫描线,每次固定一个高点,需要查询的是小于等于这个点高度的一定区域。
对于不同的颜色信息,我们可以用 k 个平衡树来维护。对于点的个数,用一个BIT来维护。

BZOJ4064——Ohters——Binary
这题是玄学,开始并没有想到好的方向。
然后发现我们可以把一个区域内的点看成一个点集,最后就是判断点集的个数是否等于总区域数。
但是我并不会处理这个东西,所以弃疗。(而且看起来好麻烦)
考虑对于每个区域要么在第 i 条直线的上方,要么在下方,所以每个区域实际上就是一个长度为 n 的二进制串。
实际上每个点我们也可以这样子来考虑,表示成一个二进制串,可以算出这些点处在多少个不同区域内。
因此算出有多少个区域,如果在不同区域里的点数等于区域数则每个区域都至少有一个点。

BZOJ4065——Map——Hamilton_Loop
如果当前节点与2个叶子相连,则要上来通过这个点再下去,同时删掉它和父亲的边。
如果与1个叶子相连,那它是途经的点,贡献照常给父亲,继续向上走即可。
如果与0个或超过2个叶子相连,那就真的无解了。
按照这样处理后可以保证一颗树里不包含不合法的边,但是这是两颗树合在一起,检查合法还需做一遍dfs,看剩下的边是否组成一个环。

2.4

BZOJ3113——Math——Polya
这是一道什么都有的数论题,我想的时候一脸懵逼,根本不会做。
在使用“特殊方法”后搞了出来,但是码的过程也一波三折。
包含素数筛选,求解欧拉函数,BurnSide引理,二分模拟乘法(快速乘),递推的构造,矩阵快速幂,置换群,枚举………
解法见题解

BZOJ3114——Math——Prime
考虑 a b 的lcm是 n 的条件,发现是对于每个质数的幂次, m a x ( a 的幂, b 的幂)= n 的幂。
发现每一位是独立的,所以不需要 2 n 枚举,每位单独算然后乘起来就行了。

BZOJ3115——DP——Common
其实不想叫它dp
打个表,把元素周期表放进去,然后就是匹配了,令 f [ i ] 表示前 i 位能否被表示,每次只用看 f [ i 1 ] 或者 f [ i 2 ] 拼一个字符串是否可行。

BZOJ3117——Simulation——Data_Structure
线段树维护空序列,然后用平衡树维护一下任务序列就好了。
翻了一下题解发现可以直接用链表暴力EXM?跑得比我的算写法快多了。(可能因为是1999的题)

不要问我为什么没有3116,我不会做,也没发现题解。

然后今天家里台式坏掉了,我整了2h没整好,暂时只能用手提了。
明天拿去修看看能保多少资料吧。明天应该会少做一点题。

2.5

然而早上自己用1.5h修好了电脑呢。正常做一做题吧。还是日常被家长劝退很多次TAT。

BZOJ3118——Linear_Programming——Simplex
日常第一题最难。
首先对于树边只可能减少,非树边只可能增加。
我们把树建好,考虑增加一条非树边,当非树边的两个端点之间路径上的边有比当前非树边小的时候,可以替换。
即对于每条非树边 i ( u , v ) ,在树上 u v 路径上的所有边 j
都需要满足 W i + X i W j X j
X i + X j W j W i
最后我们要最小化 C i X i
将矩阵转置,得到对偶问题,用线性规划单纯形法求解

BZOJ3119——Greed——Math
首先对于一项来说 + A B 都是对后面每一项都造成影响的。于是我们设一共加了 x A y b ,可得:
a x + b y = M N X 以及 x + y = n ( n 1 ) 2
从后向前贪心地选取大数进行组合即可。

BZOJ3120——DP——Compression
状态记录一下有几行结尾连续的1的个数为0,几行结尾连续的1的个数为1,当前有多少列为全1。
后三维压一下,然后矩乘转移就好了。
看似稳如老狗,实际上弄个这么大的矩阵吓死了TAT(150*150左右吧)

BZOJ2383——Others——Monotone_Stack
随机选题,开始做CEOI2011了。
显然有 r [ i ] = m i n { ( a [ i ] a [ j ] ) 2 4 r [ j ] } ,然后感性理解吹气球的过程,
不妨从当前有用的气球一个个尝试,如果比当前有用的气球最右边一个半径大那么那个气球就没用了。
这样一直做下去直到比最右边那个要小,这个时候就是膨胀的极限了。

BZOJ2384——String——KMP
序列满足条件可以由每个数前面比它小的数的个数判定。这个东西可以用KMP来做。
考虑KMP求 n e x t 数组的过程:当满足条件时从前一个递推到后一个。那么可以使用树状数组维护比一个数小的数的个数,当当前小于该数的数的个数不等于应有的个数时就减少长度,并暴力将减掉的数从树状数组中删除。
由于每次 n e x t 减少对应的是前面的 n e x t 的增加,而 n e x t 每次只增加1,因此对于每个字符的均摊时间复杂度是 O ( l o g m ) 的。之后匹配类似。
其实修改一下KMP中判断相等的条件,这题可以做到线性时间内出解。
我们维护每个数前面所有比它小的数中,最大的数的位置(即刚好比它小的数的位置),和刚好比它大的数的位置。
然后只要S中的对应位置也满足对应的关系,就认为是相等。
不过我写了树状数组的。线性的后来copy了网上题解,确实快了不少(这不废话吗)

明天开始要写寒假作业了啊,好多好多的寒假作业。然而题还是依旧刷~

2.6

然而还是并没有怎么做作业,明天考虑刷10天的物理?少做两题qwq。

BZOJ2385——Greed——Common
最朴素的贪心。
考虑将订单按价格从高到低排序,然后按顺序安排最便宜房间并求出收益。然后把最大的o个收益加起来就好了。
这样显然是对的,因为如果房间有冲突,显然会满足价格最高的;另一方面如果2个订单对2个房间可以任意分配,那么将价格高的订单分配便宜的房间或是贵的并没有影响。

BZOJ2386——DP——Common
容易发现最优解之一是所有人都按a[i]排序后再一段一段分开
如果不是这样的话,总会可以通过一些交换使之变成有序的
考虑dp,排序后 f [ i ] = m a x f [ i k ] + 1 , k <= a [ i ]
用一个辅助数组 g 保存一下到当前位置的最大答案,可以做到除去排序 O ( n ) 解答

BZOJ2587——DP——Common
其实和BZOJ2386是同一题,不过要求输出一种方案,顺手水了吧。

BZOJ2387——Map——Tarjan——DP
首先任意两条路没有交叉。
这说明一个点能到达的右侧的点一定是连续的(永远到不了的除外)。
那么tarjan缩点以后dp出每个点能到达的最小和最大的编号即可。

BZOJ2388——Divide_Conquer——Divide_Block——Common
这题WA*4,RE*1,十分不爽。
貌似我们没有什么数据结构可以用来做,于是乎分块暴力。
首先需要维护动态前缀和,对于一个点 s l < s < r ,那么 s 需要增加的值为 ( s l + 1 ) c ,如果 s 位于首尾块内,那么就可以直接暴力修改,如果 s 位于中间的块内,那么对于每个块要记录出该块首项需要加的值,以及该块中各个点的公差。对于在 r 点右边的块,就可以直接打标记记录该块的每个点需要增加的值。这需要用三个数组来记录。
查询时,与 l , r 位于相同块的点直接暴力查询即可,位于 l , r 中间的块的点,需要在每个块内维护一个凸包,可以发现,如果斜率是凹的点一定不会是最优,这样就可以对于每一个块内进行二分查找。

BZOJ2389——Map——Count
求一幅图回路个数,然而选择的路可以不在回路里面…属于搞笑题吧qwq。
一条路只有走与不走的两种状态,当加入这条边时,如果这条边所连接的两个端点已经联通, a n s = a n s 2 + 1 ,因为所有的方案可以把这条边包括进来,构造出来一种新的方案。
用并查集维护就可以了。

2.7

今天做了一下作业,然而做的还是不多qwq。听说很快就要开学了,有那么一点可怕啊。

BZOJ2391——Calc_Geometry——Triangulation
get到新技能了qwq。三角剖分+平衡树维护。从这里学的。
在这题,可以采用在剖分后,以每个三角形内部的点的权值和为面积,采用叉积算多边形一样的方法回答询问。
要维护一个 f [ i ] [ j ] 数组,表示原点和 i , j 两点构成的三角形的面积。

做法的话,首先,新建一个点 p [ 0 ] ,坐标为 ( I N F , I N F )
然后用这个点对其他点进行一次极角排序。
然后按极角序依次对于每个点建立一棵平衡树,平衡树内部采用以当前点为原点的极角序作为比较关键字。
每次对于一个点i,将极角序在它之后的点依次插入它的平衡树,在插入一个点j后,三角形 ( 0 , i , j ) 内部所有点的权值和,即为此时j在平衡树中的所有排名在它之前的点的点权和。

可以通过此预处理出所有形如 ( 0 , x , y ) 的三角形的答案。
那么在得到这些以后,只需要按照叉积算多边形面积一样的方法,即顺时针加上,逆时针减去即可, O ( n ) 回答询问。

BZOJ2393——Math——Inclusion_Exclusion
打表发现 10 10 以内的baka数只有2000个左右,在去掉有倍数关系的数后只有不到1000个。
考虑容斥原理,总数=是一个数的倍数的数的数量-是两个数公倍数的数的数量+是三个数公倍数的数的数量
枚举到某n个数的公倍数 就是对这n个数做一下LCM,然后利用容斥原理将r/lcm-(l-1)/lcm 计入答案。
然后当数字超过 10 10 就retur剪枝什么的,可以跑的飞快。
最后本地Linux实测还要用ull才能过极限数据(不过貌似极限数据是10^9,所以并不用ull)

BZOJ2395——Map——MST
最小乘积生成树,详见题解

BZOJ2396——Math——Matrix——Characteristic
随机生成一个 N 1 的矩阵 R
然后判断 A B R 是否等于 C R ,而前者相当于 A ( B R )
如果算出来的结果相等, A B C 几乎也相等。
这样就可以在 O ( N 2 ) 的时间里较准确判断结果是否相等。

2.8

明天做一做语文作业吧qwq,物理不想动了。主要是沉迷看番。

BZOJ2653——Data_Structure——Persistent——Segment_Tree
中位数有一种很常规的搞法,就是假设中位数为 x ,那么把 < x 的赋值 1 ,把 >= x 的赋值 + 1 ,然后看看是否有连续的一段 S u m >= 0
这种方法显然是具有单调性的,所以又可以把枚举 x 的复杂度降到 O ( l o g N ) (二分即可)
然后可以用线段树去维护连续的子段和,再维护一下左右端点,保证左右端点分别在 [ a , b ] [ c , d ] 之间即可,但是这样的线段树每次需要重建,我们不资瓷。
可以考虑利用可持久化线段树,对于假定的中位数 x ,所有比他小的数为-1,而比他大的仍为1,
这样就可以先建出一棵全1的树,然后每次再建一条-1的链,查询的时候前面的用-1,后面的用1,就可以达到要求了。

BZOJ4212——Data_Structure——Persistent——Trie
首先将字符串按照字典序排序,这样有相同前缀的串放在了一起。
然后依次将串插入一个Trie,每一个点维护一下能匹配到这个点的串的左右端点
然后将每个串反过来建立可持久化Trie。
对于每一个询问,首先在Trie上匹配一下,看匹配到的左右端点是什么。然后在可持久化trie的这段区间中查找有多少个能匹配的后缀就行了

BZOJ4971——Others——Construct——DP
因为 n 40 考虑构造 k ( k 20 ) 1 frac w 2 w 1 f[i][j] i 1 j k w i C^i_k$,用完全背包计算出拼出每个方案数的最少物品个数即可。
注意特判方案数为0的情况。

BZOJ4972——Others——Prefix_Sum
维护一个等腰直角三角形前缀和,一个矩形前缀和即可。

BZOJ4974——String——KMP
KMP逆操作…其实很久之前已经水过了。

其实本来今天想做可持久化专题的,不过发现自己对可持久化的理解还不是很够,决定放到年后学习。
年前年中还是以刷杂题为主,看看已有知识还有哪些不熟悉。顺便补一下番。

2.9

今天写了点语文作业,发现阅读真麻烦qwq。
然后就开始颓OI了。补完春物了qwq,雪乃股++

BZOJ4973——Map——MST
考虑最后答案的形态,必定是一个森林。这样求出这个图的最小生成树,那么非树边肯定不需要去占领。
对于每个连通块,所需的特种兵数量为 m a x ( a , c ) ,那么肯定要选 b 最小的那个点去空降。
考虑最小生成树的Kruskal算法,在算法进行的过程中,碰到非树边就扔掉。
对于每个连通块,维护 a 的最大值 v a S b 的最小值 v b S ,以及占领这个连通块的最优代价 f S
然后就是一个简单的转移。

BZOJ4975——Others——Miscellaneous
考虑一次合法的操作,它将导致长度为 l 的区间进行翻转,也就是逆序对个数和顺序对个数进行交换。
逆序对个数与顺序对个数之和为 c n t = l ( l 1 ) 2
考虑 l = 4 x + 2 的情况, c n t = ( 2 x + 1 ) ( 4 x + 2 ) c n t mod 2 = 1 ;然后考虑 l = 4 x + 3 的情况, c n t = ( 4 x + 3 ) ( 2 x + 2 ) c n t mod 2 = 1
这说明每次操作后顺序对的个数的奇偶性一定会变化,而游戏终止的时候顺序对个数为0。
故若顺序对个数为偶数,则先手必败,否则先手必胜。

BZOJ4976——DP——Common
如果 n k 17 ,那么我们对于每一位都选一个对应位为1的宝石即可(如果可以),这种情况下我们将所有宝石异或一下就行的。接下来我们只需要考虑 n k < 17 的情况,即 n < 117
直接背包DP即可。

BZOJ4977——Greed——Common//——Data_Structure——Segment_Tree
一道贪心可做,std思想很精妙(线段树模拟费用流增广)的题目。老规矩上题解

BZOJ4978——Others——Random
取一个阈值 K ,若 c i K ,那么可以通过 O ( K 2 ) 的枚举所有满足 a i + b j K ( i , j ) 直接得到这些 c i
K 取9000时,在 n = 100000 的随机数据中,剩下的还未计算的 c i 的个数平均只有450个,对于每一项暴力 O ( n ) 计算即可。

BZOJ4979——Divide_Conquer——Divide_Conquer
一道被一眼看破是分治的不错的题目。
然而这样我还是挂了两发。详情看可爱的题解

今天写了两篇题解呢。
BZOJ的月赛题还是不错的,其实感觉可以一天做一套?简单题难题都有,而且貌似都在能力范围内呢。
明天写一套,回老家写一套吧qwq。

2.10

这是这篇记录的最后一天了qwq。(然而还是一如既往地颓)
今天写的题目都不错呢,码起来也挺复杂的。(AC率蹭蹭蹭往下掉)

BZOJ3700——Map——LCA
题面是关于超帅的黄学长的!
因为顾客是 10 3 级别,完全可以枚举两个顾客。
那么剩下的问题就是在很短的时间内判断两个顾客是否会相遇。
然后其实就是一个路径求交,分情况讨论即可。LCA用树剖或者欧拉序 O ( 1 ) 去求,不然大概率TLE。
表示19s卡过去了qwq,双倍经验BZOJ1906

BZOJ3701——Math——Mobius
这个显然要转化为前缀和问题是吧,我们设当前要算距离在 k 以内的点对数。
考虑枚举一维的差值 d x = a b s ( x 1 x 2 )
那么答案显然就是 ( n d x + 1 ) j = 1 d x 2 + j 2 <= L [ g c d ( d x , j ) == 1 ] ( m j + 1 )
然后莫反一波就行了。(而且这个题不用下底分块啊,很舒服)
当然的话你不想用莫反公式,硬推容斥也是可以推出来的。

BZOJ3702——Data_Structure——Segment_Tree
对于每一个节点,保证这个子树代表的区间里逆序对数最少,即能保证答案最小,因为两颗互不包含的子树内部的顺序与一颗子树对另一颗子树的贡献无关。
那么我们对每个叶子节点建一个权值线段树,对每个非叶子节点合并他的两个儿子节点的线段树,合并有点类似可并堆。
合并的时候通过 s i z [ s o n [ x ] [ 0 ] ] s i z [ s o n [ y ] [ 1 ] ] s i z [ s o n [ x ] [ 1 ] ] s i z [ s o n [ x ] [ 0 ] ] 算出左儿子在前和右儿子在前时候的子树内逆序对数,用其中较小的一个更新答案。

BZOJ3703——Search——DFS
正解的用时应该是很短的。但我并没有想到什么好的方法。
于是暴搜+各种剪枝把这题跑过了。(当然是通过BZOJ的卡时技巧)

BZOJ3704——Greed——Math
先考虑构造合法解,每次都对一个后缀加上一定的值。
对于合法解的优化,我们可以在差分序列上选择一位进行-4 操作,相当于对后缀-4,可以节省的代价根据(当前位-上一位)决定。
所以,我们先对于差分序列中为 的位置考虑-4,可以节省 3的代价。
剩下的依次贪心,注意判断序列合法性。

猜你喜欢

转载自blog.csdn.net/dream_lolita/article/details/79220537