Decode(ZOJ 3636)
给定k个长度为n的01向量以及异或运算,就得到了一个集合S($$ x \in S $$当且仅当从k个向量中取若干个异或起来可以得到x)。再给定m个询问,每个询问包含一个01向量,要求你在容错位最多为3的前提下找一个离该向量最近并属于S的01向量。如果有多个,输出字典序最小的。
想想如果给你一个01向量,让你判断它在不在S里这是很容易办到的。具体做法就是$$x_i$$表示那k个向量的取和不取的状态,然后得到一个异或方程,高斯消元就可以了。但是注意到这里n只有30,所以那么多向量是没有用的,直接把给的向量消成上三角矩阵,得到其中有用的若干个,就可以在$$O(n)$$的复杂度内判断一个码在不在集合S内了。又由于每个码只允许改3个位,只需暴力枚举改哪三个位再用上面的方法判断就行了。
#include
#include
#include
#include
#include
#include
#include
Alice's present(ZOJ 3633)
给定一个序列$$a_i$$,每次询问一个区间内,从右往左看,第一个重复的是谁
设next[i]表示a[next[i]] = a[i]且next[i] > i的最小值,那么询问按左端点排序以后,按其降序扫过去,然后每个询问(l, r)相当于问next[i] ≤ r 的值里最大的i所对应的a[i]是多少。这个显然可以树状数组求最值,就是按next[i]为下标建立树状数组然后blablabla...其实sort后可以$$O(n)$$地用单调队列搞,按类似的思路做也不难实现。
#include
#include
#include
#include
#include
#include
#include
Bounty Hunter(ZOJ 3634)
有一只Bounty Hunter,他按顺序从城市1跑到城市n,在每个城市进行两个操作:买攻击力和做任务。在城市i,每点攻击力要花费$$a_i$$块钱。买完攻击力以后做任务时可以获得$$atp * b_i$$(atp为当时的攻击力)的钱,问最后Bounty Hunter最多能获得多少钱。
设mow[i]表示如果你在进入第i个城市之前,有1块钱,那么在之后最多能变成多少块钱,apw[i]表示如果你在进入第i个城市之前,有1点攻击力,那么在之后最多会演化成多少块钱,然后转移就很显然了,不懂就看代码吧...就像dp一样的思路,唯一需要说明的一点大概是:因为这个转换关系都是常数倍的关系,所以这些获利都可以分开考虑,最后叠加。
#include
#include
#include
#include
#include
#include
#include
Information Sharing(ZOJ 3641)
给定每个人身上所带的消息以及若干个集合的合并操作,每次动态问某个人所属的集合中,拥有的信息有哪一些。
因为保证信息数不超过1000,那么1000 * n bitset Disjoint Set暴力合并随便搞。
其实把信息数的条件去掉也可以做的,但是要保证答案size不超过多大或者直接换成输出拥有的信息的数目。这样子的做法大致是两个集合合并的时候,Disjoint Set依然是路径压缩式合并,但是set的合并要从set.size()比较小的那个逐个暴力插入到大的set里面。因为每个人最多只带10个信息,这样可以保证最后复杂度不超过$$O(10n log^2 10n)$$。
#include
#include
#include
#include
#include