做法1
对于每一个询问,直接暴力在每一个序列中二分查询
时间复杂度为$o(nk)-o(klog n)$
做法2
将所有序列合并后排序,并对每一个元素预处理出每个序列中第一个大于等于其的元素(位置),那么只需要在总序列中二分并输出该位置预处理的答案即可
关于这个预处理,显然只需要从后往前扫描一遍总序列即可
时间复杂度为$o(nk^{2})-o(k+log nk)$
做法3
使用分治归并,并对合并后序列的每一个元素预处理出参与合并的两个序列第一个大于等于其的元素位置
对于查询,只需要在总序列中二分一次,并根据预处理的信息递归下去即可
时间复杂度为$o(nklog k)-o(k+log nk)$
做法4
事实上,只需要将下标为偶数的项参与合并,此时即找到第一个大于等于"其"的偶数项,再判断上一项是否大于等于"其"即可,这样查询的复杂度并没有变化
(另外,为了避免特判可以强制将最后一项也加入)
沿用做法3,并做此优化,归纳可得每一个位置上的序列长度都为$n$,复杂度即降为$o(nk)$
当然,直接沿用做法2也是可以的,即令${b_{k}}={a_{k}}$且${b_{i}}$为${a_{i}}$和${b_{i+1}}$合并的结果,同样在合并后预处理相同的信息,通过此优化不难证明${b_{i}}$的长度和为$o(nk)$
时间复杂度为$o(nk)-o(k+log nk)$

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 10005 4 #define K 105 5 #define D 2 6 int n,k,m,d,x,ans,num[11],a[K][N],Pos[2],b[K][N<<1],pos[K][N<<1][2]; 7 int read(){ 8 int x=0; 9 char c=getchar(); 10 while ((c<'0')||(c>'9'))c=getchar(); 11 while ((c>='0')&&(c<='9')){ 12 x=x*10+(c-'0'); 13 c=getchar(); 14 } 15 return x; 16 } 17 void write(int x,char c='