Divide and conquer:Matrix(POJ 3685)

           

                矩阵

  题目大意:矩阵里面的元素按i*i + 100000 * i + j*j - 100000 * j + i*j填充(i是行,j是列),求最小的M个数

  这一题要用到两次二分,实在是二分法的经典,主要是每一列都是按照行来递增的,每一行我们都用二分法找到比mid小的那些数就好了

  参考http://blog.csdn.net/nw4869/article/details/24124019

  

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <functional>
 4
 5 using namespace std;
 6 typedef long long LL_INT;
 7
 8 LL_INT getnum(LL_INT, LL_INT);
 9 bool judge(LL_INT, LL_INT, const int);
10
11 int main(void)//这题双二分法
12 {
13     int test_sums, size;
14     LL_INT M;
15     scanf("%d", &test_sums);
16
17     while (test_sums--)
18     {
19         scanf("%d%lld", &size, &M);
20         LL_INT lb = -0x3fffffffffffffff, rb = 0x3fffffffffffffff, mid;
21         while (rb - lb > 1)
22         {
23             mid = (lb + rb) / 2;
24             if (judge(mid, M, size)) lb = mid;
25             else rb = mid;
26         }
27         printf("%lld\n", rb);
28     }
29     return 0;
30 }
31
32 LL_INT getnum(LL_INT i, LL_INT j)
33 {
34     return  i*i + 100000 * i + j*j - 100000 * j + i*j;//注意这题的每一列都是递增的!
35 }
36
37 bool judge(LL_INT x, LL_INT M, const int N)
38 {
39     LL_INT line_l, line_r, mid, sum = 0;
40     for (int col = 1; col <= N; col++)
41     {
42         line_l = 1; line_r = N + 1;
43         if (getnum(N, col) <= x)//先判断一下这个,还可以剪枝,而且还能避免判断n=1的时候的错误
44             sum += N;
45         else
46         {
47             while (line_r - line_l > 1)
48             {
49                 mid = (line_l + line_r) / 2;
50                 if (getnum(mid, col) <= x) line_l = mid;
51                 else line_r = mid;
52             }
53             if (getnum(line_l, col) <= x)
54                 sum += line_l;
55             else
56                 sum += line_l - 1;
57         }
58     }
59     return sum < M;
60 }

  

时间: 2024-11-16 01:24:53

Divide and conquer:Matrix(POJ 3685)的相关文章

Divide and conquer:Median(POJ 3579)

    快速求两数距离的中值 题目大意:给你一个很大的数组,要你求两个数之间的距离的中值 二分法常规题,一个pos位就搞定的事情 1 #include <iostream> 2 #include <algorithm> 3 #include <functional> 4 5 using namespace std; 6 typedef long long LL_INT; 7 8 static int nums[100002]; 9 bool judge(LL_INT,

Divide and conquer:Sumsets(POJ 2549)

数集 题目大意:给定一些数的集合,要你求出集合中满足a+b+c=d的最大的d(每个数只能用一次) 这题有两种解法, 第一种就是对分,把a+b的和先求出来,然后再枚举d-c,枚举的时候输入按照降序搜索就好,一旦d满足条件就是最大的了,另外判断不重复存一下位置就好,时间复杂度0(n^2*logn) 1 #include <iostream> 2 #include <functional> 3 #include <algorithm> 4 5 using namespace

POJ 3685 Matrix 二分套二分

POJ 3685 Matrix 二分 题意 有一个N阶方阵,方正中第i行第j列的元素值为\(d_{i,j}=i^{2}+1e5*i+j^{2}-1e5*j+i*j\),我们需要找出这个方阵中第M小的元素值. 解题思路 分析这个公式,我们发现:当j固定的时候,这个公式关于i(取值范围:从0到n)是单调增加的,所以这里我们可以二分一个答案,然后一列一列的找小于(等于)它的个数,这样加起来我们就能知道我们枚举的这个答案是第几小了. 需要注意的是,第一个最外层的二分有点不同,因为我们二分的答案可能不存在

分治算法学习 Divide and Conquer

分治思想: 分治算法的思想就是 对于某些特定种类的问题  如果问题的规模很小,那么就直接解决,如果问题的规模比较大,那么就把问题先分解为规模小的但是问题相同的子问题 ,并且不断分解直到规模足够小,再递归地解决这些问题 如果原问题可分割成k个子问题,1<k≤n,且这些子问题都可解并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的. 递归与分治经常是一起使用的 能够用分治的情况 : 1.问题复杂性随规模减小而减小 2.问题具有最优子结构性质        最优子结构:如果问题的最优解所包

poj 3685 Matrix(二分搜索之查找第k大的值)

Description Given a N × N matrix A, whose element in the i-th row and j-th column Aij is an number that equals i2 + 100000 × i + j2 - 100000 × j + i × j, you are to find the M-th smallest element in the matrix. Input The first line of input is the nu

Divide and conquer:Telephone Lines(POJ 3662)

电话线 题目大意:一堆电话线要你接,现在有N个接口,总线已经在1端,要你想办法接到N端去,电话公司发好心免费送你几段不用拉网线,剩下的费用等于剩余最长电话线的长度,要你求出最小的费用. 这一看又是一个最小化最大值的问题(也可以看成是最大化最小值的问题),常规方法一样的就是把这个费用二分就好,但是这道题是道图论题,不一定经过所有的点,那我们就以二分基准长度为界限,把小于基准长度的那一部分看成是0,大于等于基准长度的看成是1,这样我们只用SPFA算法算最短路径就可以了,非常的巧妙 参考:http:/

Divide and conquer:Aggressive Cows(POJ 2456)

侵略性的牛 题目大意:C头牛最大化他们的最短距离 常规题,二分法即可 1 #include <iostream> 2 #include <algorithm> 3 #include <functional> 4 5 using namespace std; 6 7 static int pos[100000]; 8 9 bool judge(const int, const int,const int); 10 void solve(const int, const i

Divide and conquer:Monthly Expense(POJ 3273)

Monthly Expense 题目大意:不废话,最小化最大值 还是直接套模板,不过这次要注意,是最小化最大值,而不是最大化最小值,判断的时候要注意 联动3258 1 #include <iostream> 2 #include <functional> 3 #include <algorithm> 4 5 using namespace std; 6 7 static int money_set[100010]; 8 9 void Search(const int,

Divide and Conquer:River Hopscotch(POJ 3258)

 去掉石头 题目大意:一群牛在河上的石头上跳来跳去,现在问你如何通过去掉M个石头,使得牛跳过石头的最短距离变得最大? 这一题比较经典,分治法的经典,二分法可以很方便处理这个问题,我们只要明白比较函数这个东西就可以了. 模板: while (……) { mid = (lb + rb) / 2; if (Judge_C(……)) else rb = mid; } while判断条件可以根据是整形还是浮点型灵活变换,Judge_C就是比较函数,几乎所有的分治算法都可以这样归纳,我们只要找到合适的比较函