POJ3685 二分求第k小的值
来源:互联网 发布:久其通用数据平台 编辑:程序博客网 时间:2024/06/05 06:17
二分的题目写了好久
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 number of test case.
For each test case there is only one line contains two integers, N(1 ≤ N ≤ 50,000) and M(1 ≤ M ≤ N × N). There is a blank line before each test case.
Output
For each test case output the answer on a single line.
Sample Input
121 12 12 22 32 43 13 23 83 95 15 255 10
Sample Output
3-99993312100007-199987-99993100019200013-399969400031-99939
因此,枚举每一列,在每一列上使用二分答案的方法
另外求第K小的数,这里有一个二分的算法
假设有一个函数cnt能够知道比M小的数有多少个,那个我们就可以进行二分了
while (right-left>1) { mid = (left + right) / 2; long long tmp = cntr(mid); if (tmp <= m-1) { left = mid; } else { right = mid; } cnt++; }
而恰好这里cnt也可以利用函数的单调性,进行二分
因此不会TE
#include <cstdio>#include <iostream>#include <cstring>#include <queue>#include <map>#include <cstdlib>#include <deque>#include <algorithm>#include <cmath>#include <set>#define INF 1e12using namespace std;#define N 50007long long n,m;long long maxer = -INF;long long miner = INF;long long f(long long i, long long j) { //对于x是单调递增的,对于y我们认为不确定,其实这里是先简后增的。 return ((i*i) + (100000 * i) + (j*j) - (100000*j) + (i*j));}long long upper_iter(long long col, long long lo, long long hi, long long target) {//统计某一列中小于target的个数有多少 long long res; while(lo<hi){ long long mid=lo+(hi-lo)/2; if((f(mid, col))<target){ lo=mid+1; res=lo; }else { hi=mid; res=hi; } } return res;}long long cntr(long long M) { //统计矩阵中<M的数有多少个 long long ans = 0; for (long long i=1;i<=n;i++) { //每一列 ans += upper_iter(i, 1, n+1, M) - 1; } return ans;}int main() { //freopen("in.txt", "r", stdin); long long cases; cin >> cases; while (cases--) { maxer = -INF; miner = INF; cin >> n >> m; //最小值一定在第一行,最大值一定在最后一行 long long left = -INF; long long right = INF; long long cnt = 0; long long mid; while (right-left>1) { mid = (left + right) / 2; long long tmp = cntr(mid); if (tmp <= m-1) { left = mid; } else { right = mid; } cnt++; } cout << left << endl; }}另外注意的一点是爆longlong了,刚开始没有注意总是WA,后来对拍了一下发现了问题,并且那个最大值和最小值分别设置成1e12比较合适
0 0
- POJ3685 二分求第k小的值
- poj3685(二分查找第k小)
- POJ3685 Matrix (二分-查找第K大的值)
- hihocoder1133(二分求第k小)
- poj3685 Matrix(第K大的数)
- 求第k小的数
- Java 求第K小的数
- 求第k小的数
- 【分治】求第k小值
- hdu 2104 K-th Number(静态求区间第k小+整体二分)
- 二分求两个有序数组第k大的数
- Leetcode#4.Median of Two Sorted Arrays(归并排序&二分查找求第k小的数)
- 求第k小元素
- 计蒜客-求第k小
- 计蒜客-求第K小
- poj3579(二分求解第k小/大值)
- HDU 5412 CRB and Queries 求区间第k小 CDQ分治+整体二分
- hdu 5412 CRB and Queries(动态求区间第k小+整体二分)
- Docker的“谎言”
- 以生活例子说明单线程与多线程
- Web应用启动时,后台自动启动一个线程
- 二进制 原码、反码、补码
- Mysql优化
- POJ3685 二分求第k小的值
- sort和qsort排序
- Android学习笔记——Handler消息分发
- 织梦dedecms生成栏目HTML缓慢的一个可能原因及解决方法
- Assets文件下文件读取方式
- MySql查询优化,高并发控制
- hdu 5738 多校2 Eureka 【几何计数】
- Android 获取设备常用信息 (app版本信息 签名信息)
- Netty解决半包(TCP粘包/拆包导致)读写问题