T1:首先a[1]=b[1]。然后,假设我们知道了a[1~i*2-3],现在要求a[i*2-2]和a[i*2-1],那我们可以这样做。
令s0表示a[1~i*2-3]中有多少个数小于b[i],s1表示a[1~i*2-3]中有多少个数大于b[i]。然后我们来分类讨论一下。
若b[i]在a[1~i*2-3]中出现过,则1、若s0=s1,那么要填入一个大于b[i]和一个小于b[i]的
2、若s0<s1,那么要填入两个小于b[i]的
3、若s0>s1,那么要填入两个大于b[i]的
若b[i]没有出现过,则在这两个数中一定要填一个b[i],接下来考虑剩下一个数要填什么
1、若s0<s1,则填一个小于b[i]的
2、若s0>s1,则填一个大于b[i]的
注意:s0不可能等于s1。
那么要填那种数我们已经确定了,关键是填那一个数。我们知道b[1]的取值范围是1~n*2-1,b[2]是2~n*2-2,b[3]是3~n*2-3……也就是说i越往后,越极端的数越不可能成为中位数,而且因为这些数比较极端,所以他们更容易满足条件。那么也就得出了结论:每一次填入一个当前还没填的数中最大或最小的,这个可以用标记处理。至于s0和s1,可以用线段树维护。
T2:不会,要用莫比乌斯反演。
T3:首先要发现一个性质:若选出来的叶子节点是合法的,那么序列中的每一个数一定等于一个常数乘一个2的幂。为了方便处理,我们可以枚举这个常数,然后把所有数都除以这个常数,得出一个新的序列。注意,被除数必须是常数的倍数,且商必须是2的幂。得到新序列后,我们考虑用dp。
设f[i][j]表示前i个数选出来的数的和为j的最多个数。那么我们考虑a[i+1]选不选。若要选,则一定要满足以下形式:
|---|
|-8-|---|
|---|-4-|-2-|加上一个2
也就是j为a[i+1]的倍数。若满足这个条件,则可以用f[j]+1更新f[j+a[i]]。
答案就是max(f[2^k]),意思是最终合成一棵树。
优化:首先数组可以滚动。然后为了优化时间,我们可以把所有数先放进一个小根堆里,然后每次取出一个最小值,然后以这个最小值作为常数做一遍dp。每一次把合法的数打上标记,下一次就不以这些数为常数了。