二分——GDUT #C 进击的调查兵团

  • 题目链接: 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");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值