题目链接: http://gdutcode.sinaapp.com/problem.php?cid=1054&pid=2
题意: 每次查询A数组的区间1和B数组的区间2的并的第K小,给出的数组都是递增排好的
分析:如果没有后面那个条件,这道题就需要用到复杂的数据结构来搞了。不过既然是排好序的,我们就可以直接二分搜索。取L为两个区间的最小值,R为两个区间的最大值,那么在这个范围(L,R)内二分搜索第K小值,对于每一个mid,我们同样在区间1和区间2中二分查找mid的位置,那么它前面的数都比它小,加在一块如果小于K,那么L = mid+1;如果大于等于K,那么R = mid-1。
注意:因为数值范围最大为2^31次,所以做求和操作的时候注意不要爆int
AC代码:
/*************************************************************************
> File Name: test.cpp
> Author: Akira
> Mail: qaq.febr2.qaq@gmail.com
************************************************************************/
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <ctime>
#include <climits>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;
#define MaxN 100001
#define MaxM MaxN*10
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
const int mod = 1E9 + 7;
const double eps = 1e-6;
#define bug cout<<88888888<<endl;
#define debug(x) cout << #x" = " << x;
int T;
int N, M, Q;
LL A[MaxN];
LL B[MaxN];
int main()
{
//std::ios::sync_with_stdio(false);
scanf("%d", &T);
while (T--)
{
scanf("%d%d%d", &N, &M, &Q);
for (int i = 0; i < N; i++) scanf("%lld", A + i);
for (int i = 0; i < M; i++) scanf("%lld", B + i);
int l1, r1, l2, r2;
LL k;
while (Q--)
{
scanf("%d%d%d%d%lld", &l1, &r1, &l2, &r2, &k);
LL l = min(A[l1], B[l2]), r = max(A[r1], B[r2]);
while (l < r)
{
LL mid = (l + r)>>1;
int a = lower_bound(A + l1, A + r1+1, mid) - A;
if(A[a]==mid)a++;
int b = lower_bound(B + l2, B + r2+1, mid) - B;
if(B[b]==mid)b++;
if (a + b < k+l1+l2) l = mid + 1;
else r = mid;
}
printf("%lld\n", l);
}
}
//system("pause");
}