51nod算法马拉松32

好像已经一年没更新这个blog了。。
临近期末,无心预习。。就打了场51nod。。感觉要退学了。。

A.
先把A和B的特殊表示法加起来,从前到后处理每一位,需要维护一个向前延伸的最长的01间隔的序列。
复杂度 O(n) .

调了一晚上+一上午被告知数据错了。。

为什么题解说直接模拟就可以了呀??怎么模拟啊??
B.
想了一天,Google了一发才发现原来有个叫Prüfer编码的东西。。(bzoj1005竟然就是用这个做的,一直不会呢。。)
每一个有标号无根树都与一个长度为n-2值域在1~n的序列一一对应。
这个序列的构造方式是每次选择一个编号最小的叶子节点删掉,把与这个叶子节点相连的节点记到序列里,这里叶子节点被定义为度数为1的节点。
因为最后所有的节点度数都不超过2,所以每一个非叶子节点都会有一条与之相连的边被删掉,此时这个非叶子节点一定不会被删,所以它便会被记到序列里。所以一个节点在某一时刻是叶子节点当且仅当它不曾在之后的序列出现过。那么每一时刻我们就可以知道当前叶子节点的集合和此时被删掉的叶子节点的编号,就可以还原出这棵树了。
于是这道题就是一个很简单的容斥了:求长度为n-2的序列种出现且仅出现n-m个数的方案数。

挖个坑:以后有时间的话研究一下有无标号有无根树是否区分儿子顺序的树的计数问题吧。
咦??题解好像不是用Prufer做的,他在说什么??
C.
脑补了一下觉得正经做的话可以整体二分^3/整体二分+kd-tree。
于是写了一个 O(n2) 暴力卡了卡果然就A了,非常开心。

然而题解竟然是。。线段树+bitset???这么劲的么。。
D.
唯一一道看起来和善的题。
回忆了一下manacher(虽然从来没写过),从manacher的流程中可以看出一个长度为n的串的不同的回文子串不会超过n个。
那么把它们hash一下,计算两个字符串相同的回文子串数目的代价是较短串的长度。
所以对于串长大于 n 的串,可以预处理两两之间的答案,时间复杂度是 O(nn) 。串长小于 n 的串,询问的时候直接做就好了,时间复杂度是 O(nn)
其实预处理的过程也可以延后到查询中,只要在查询中记忆化一下就可以了。
用set竟然会T,只好用unordered_set了。

终于有一道做法和题解一样的题了。
E.
把给出来的东西质因子分解,然后从大到小枚举c,那么就是要支持全局减、单点修改、查询最小值的东西,用堆就可以了,时间复杂度是 O(nlognloglogn)/O(nlog2n)
上面都是我看了题解之后才恍然大悟的,我十分智障地写了个分块。。
F.
写了一个 O(Plogm+m) O(mloglogm) 的全都T了,只好把数据cheat出来了。。

想了想发现甚至自己骗数据的方法也不太科学,如果说数据有n个数,每个数的值域是 ai ,一共有T组数据。
我们本来想的是二分每一个数,需要的时间是 Tni=1log2ai
我们既然有WA,TLE,RE,MLE四种状态,那么我们可以把这n个数四进制分解,一位一位来求,这样好处是可以把T去掉,并行地来求,需要的时间是 ni=1log4ai 。像是这道题,就只需要交29发。

看了一下题解,和我的做法的最大区别在于我是反演的它是杜教筛的。对啊,这种只求一个数的东西,为什么要反演呢?肯定是杜教筛啊!!
另外题解一上来甩了一个非常有趣的结论:
lcm(x1,x2,...,xn)=nk=1y1<y2<...<ykgcd(xy1,xy2,...,xyk)(1)k1
看起来很像反演,也确实可以用跟反演一样思路归纳证明。
对称的式子:
gcd(x1,x2,...,xn)=nk=1y1<y2<...<yklcm(xy1,xy2,...,xyk)(1)k1
对数版本:
max{a1,a2,...,an}=nk=1y1<y2<...<yk(1)k1min{ay1,ay2,...,ayn}
对称的对数版本:
min{a1,a2,...,an}=nk=1y1<y2<...<yk(1)k1max{ay1,ay2,...,ayn}
感觉非常神奇呢。

感觉以后有时间可以重新做一遍这套题,根本看不懂题解啊。。现在先去复习吧。

猜你喜欢

转载自blog.csdn.net/ta201314/article/details/78945265