算出长度,显然奇数不行,然后遍历一遍,奇数位为'm',偶数位为'q'。(下标从1开始)
思路:
M个序列里分别选一个数,我们先从第一行和第二行来合并出新行,再用新行与第三合并,依次类推,最后的新行的前K个数的即为答案。
设数组A为第一行,数组B为第二行。合并的为C数组
先将A从小到大排序,那么我可以得到的新数组为:
A【1】+ B【1】, A【1】+ B【2】,A【1】+ B【3】...... A【1】+ B【M【B】】(M【B】为B的个数)
A【2】+ B【1】, A【2】+ B【2】,A【2】+ B【3】...... A【2】+ B【M【B】】
A【3】+ B【1】, A【3】+ B【2】,A【3】+ B【3】...... A【3】+ B【M【B】】
A【4】+ B【1】, A【4】+ B【2】,A【4】+ B【3】...... A【4】+ B【M【B】】
......
A【M【A】】+ B【1】,...... 共M【A】* M【B】个
显然每列的第一个数为每列的最小值
我们的目的是求前K个最小值,所以我们C数组的长度为 min( K, M【A】* M【A】);
对应合并我们需要的操作是求最小值,插入新的值和删除,显然优先队列可以满足我们的条件,先将第一行放入优先队列,并加一个下标标记,对于取出的最小值,就插入他对应的下一行。直到取到K个值就可以了。总共合并N - 1 次即可。
思路:
着实坑,首先要知道第一个数如果不是 m - 1 或 m ,答案就为 0;因为第一个数只能加 1 次。
可以类比为括号,左括号表示操作区间的左端点,右括号表示操作区间的右端点,则一个位置不能出现两个及以上的左括号或右括号。
那么对于任意一个位置都有四种情况:
1. 没有括号;
2.只有左括号;
3.只有右括号;
4.同时包含左括号和右括号。
那么我们可以设 f [ i ] [ j ] 为前 i 个位置,左括号比右括号多 j 个情况下并且 [1, i] 的区间中任意一个数等于 m 的方案数。
对于不放括号:f [ i ] [ j ] += f [ i - 1] [ j ];
对于只有左括号:f [ i ] [ j ] += f [ i - 1] [ j - 1];
对于只有右括号:f [ i ] [ j ] += ( j + 1) * f [ i - 1] [ j + 1];
(在第 i 个位置放了右括号后,左括号还比右括号多 j 个,则 [ 1, i - 1]里左括号比右括号多 j + 1 个。乘上 j + 1 是因为给这个右括号可以匹配的左括号有 j + 1 个);
对于同时包含左括号和右括号:f [ i ] [ j ] += ( j + 1) * f [ i - 1] [ j ] ; (道理同上);
其中情况 1 和 情况 2 ,a [ i ] 都加 了 j
情况 3 和 情况 4 , a [ i ] 都加了 j - 1
最后答案即为 f [ n ] [ 0 ];
思路:
对于三元组的情况,任意一个数的贡献是 左边比他小的 * 右边比他大的,我们是用树状数解决的, 所以这道题就是在三元组上面的拓展;
先可以得到递推式:$f[i][j] = \sum\limits_{k=1}^{i-1}f[k][j-1](a_k<a_i)$