[POJ 2104] K-th Number (块状数组)
来源:互联网 发布:mac记事本 编辑:程序博客网 时间:2024/04/29 23:58
POJ - 2104
给定一个长度为 N的互不相同的序列和 M个询问
每次询问给出一个区间,问区间内第 K大的数是多少
分块做法:
将区间分块,每块大小 sqrt(n),分块内排序
每次查询一个第 K大,先二分确定这个数是多少
然后在区间内统计小于他的数有多少个,如果 cnt>=K,则缩小这个数 (log(n))
统计方式是,每次查询的一个区间
如果完全包含了一个分块,则在分块内二分搜索 (n/sqrt(n)=sqrt(n))
而不完全包含分块的部分,则暴力地一个个查找 (sqrt(n))
时间复杂度 O(m*log(n)*sqrt(n))
分块第一题,说一下感想:
1) 要注意分块的时候,右边界的处理,他可能会超过 N,要判断下
2) 关于为什么块的大小是 bsiz=sqrt(n)
很显然,每次查询的复杂度是 n/bsiz + bsiz,由基本不等式可得
当 bsiz=sqrt(n)的时候,这个复杂度有最小值 sqrt(n)
关于这题的一些坑点:
1) 二分查找的时候,不是在 [-INF, INF]范围查找,而是对原数组排序,在原数组里查找值
2) 这题分块的大小要强制限定为 1000,不要问我为啥不是 sqrt(n),因为玄学
#include <cstdio>#include <iostream>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <map>#include <set>#include <queue>using namespace std;typedef pair<int,int> Pii;typedef long long LL;typedef unsigned long long ULL;typedef double DBL;typedef long double LDBL;#define MST(a,b) memset(a,b,sizeof(a))#define CLR(a) MST(a,0)#define Pow2(a) (a*a)const int maxn=1e5+10,INF=1e9+10;int N,M,bsiz;int inpt[maxn];int sarr[maxn];int arry[maxn];template<typename T> inline void read(T &x){ x = 0; T f = 1; char ch = getchar(); while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();} while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();} x *= f;}int Cnt(int,int,int);int main(){// #ifdef LOCAL// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// #endif while(~scanf("%d%d", &N, &M)) { for(int i=0; i<N; i++) { scanf("%d", &inpt[i]); sarr[i]=inpt[i]; } sort(sarr,sarr+N);// bsiz=sqrt(N); bsiz=1000; int front=0; while(front<N) { int rear=front+bsiz; if(rear>=N) rear=N; for(int i=front; i<rear; i++) arry[i]=inpt[i]; sort(arry+front,arry+rear); front=rear; } int x,y,k; for(int i=1; i<=M; i++) { scanf("%d%d%d", &x, &y, &k); int l=0,r=N-1; while(l<r) { int mid=(l+r+1)>>1; if(Cnt(x-1,y,sarr[mid])>=k) r=mid-1; else l=mid; } printf("%d\n", sarr[l]); } } return 0;}int Cnt(int ql, int qr, int num){ int np=ql,tcnt=0; while(np<qr) { int pos=np/bsiz,bl=pos*bsiz,br=pos*bsiz+bsiz; if(ql<=bl&&br<=qr) tcnt+=lower_bound(arry+bl,arry+br,num)-(arry+bl); else { int l=max(ql,bl),r=min(br,qr); for(int i=l; i<r; i++) { if(inpt[i]<num) tcnt++; } } np=br; } return tcnt;}
0 0
- [POJ 2104] K-th Number (块状数组)
- [POJ 2104] K-th Number [块状链表]
- poj--2104--K-th Number(伴随数组)
- 【poj 2104】K-th Number(整体二分+树状数组)
- poj 2104 K-th Number
- poj 2104 K-th Number
- Poj 2104 K-th Number
- POJ-2104-K-th Number
- POJ 2104 K-th Number
- POJ-2104-K-th Number
- POJ 2104 K-th Number
- POJ 2104 K-th Number
- POJ 2104 K-th Number
- POJ 2104 K-th Number
- POJ 2104 K-th Number
- poj-2104 K-th Number
- POJ 2104 K-th Number
- 【POJ 2104】K-th Number
- 利用surfaceview 文字横竖向滚动
- 状态栏颜色
- ClassLoader referenced unknown path: /data/app/XXX-1/lib/arm
- Docker Swarm入门教程
- c++第4次作业
- [POJ 2104] K-th Number (块状数组)
- android倒计时,使用CountDownTimer
- Git 常用命令整理
- 前端性能优化--高性能网站建设读书笔记
- 数组中的逆序对
- mongo 2 查询语句
- STL vector 循环没有运行就跳出问题 解决
- 我的cocos2D-X3.10安装之路
- Linux Shell脚本编程--Uniq命令