块状数组+归并树学习 poj2104+hdu2665
来源:互联网 发布:图像处理滤波器java 编辑:程序博客网 时间:2024/05/29 19:02
今天在大白(挑战程序设计)上重新看了一遍分块数组相关的内容,虽然以前看过了,也做过相关的题目,但是总感觉只知道思想,自己不敢实现,今天把上面的例题照着敲了敲,也算加深了印象吧。
例题:POJ2104和HDU2665
这两个是题都是求区间第K大,只不过HDU上数据强并且时间限制少了点。
以前以为平方分割求这种题还挺快的,没想到啊。。在POJ 11000+ms勉强水过,在HDU无情T掉。
不过归并树倒是有些出乎我意料的快,POJ 6000+ms,HDU 3500+ms
归并树之所以叫归并树是因为这一整棵树刚好是归并排序的完整再现。
今天除了温习了这两种数据结构,新收获是get了库函数merge的用法,以及!以后在这两个OJ上交题千万注意的一
点 ! 当你交C++ T了的时候不妨交一发G++试一试,极大可能会有惊喜,上面这两种算法我交C++都是TLE,很气。
PS:区间第K大一类的问题好像是主席树裸题,看人家400+ms轻松跑过的题而我要跑11000+ms,真的是欲哭无泪啊,改天膜拜一下主席树回来再战!
poj 的块状数组代码:
#include<iostream>#include<algorithm>#include<vector>#include<stdio.h>#include<math.h>using namespace std;const int MAXN=100010;const int B=1000;vector<int>bucket[MAXN];int a[MAXN],tmp[MAXN];void init(int n){ for(int i=0;i<n;i++) { bucket[i/B].push_back(a[i]); tmp[i]=a[i]; } sort(tmp,tmp+n); for(int i=0;i<n/B;i++) sort(bucket[i].begin(),bucket[i].end());}int check(int mid,int tl,int tr){ int x=tmp[mid]; int cnt=0; //区间两端多出的部分 while(tl < tr && tl % B) if(a[tl++] <= x) cnt++; while(tl < tr && tr % B) if(a[--tr] <= x) cnt++; //对每一个桶进行计算 while(tl < tr) { int b = tl / B; cnt += upper_bound(bucket[b].begin(), bucket[b].end(),x) - bucket[b].begin(); tl += B; } return cnt;}int solve(int L,int R,int K,int n){ int l=0,r=n-1,mid; while(l<=r) { mid=(l+r)>>1; if(check(mid,L,R+1) >= K) r = mid-1; else l = mid+1; } //cout<<l<<" "<<r<<endl; return tmp[r+1];}int main(){ int n,m,l,r,k,T; //cin>>T; //while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",a+i); init(n); while(m--) { scanf("%d%d%d",&l,&r,&k); printf("%d\n",solve(l-1,r-1,k,n)); } }}
#include<iostream>#include<stdio.h>#include<algorithm>#include<vector>#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;const int MAXN = 100010;int a[MAXN];vector<int>tree[MAXN<<2];void build(int l,int r,int rt){if(l==r){tree[rt].push_back(a[l]);return ;} int mid=(l+r)>>1;build(lson);build(rson);tree[rt].resize(r-l+1);merge(tree[rt<<1].begin(),tree[rt<<1].end(),tree[rt<<1|1].begin(),tree[rt<<1|1].end(),tree[rt].begin());}int query(int L,int R,int x,int l,int r,int rt){if(L<=l&&r<=R){return upper_bound(tree[rt].begin(),tree[rt].end(),x)-tree[rt].begin(); }int mid=(l+r)>>1,sum=0;if(L<=mid)sum+=query(L,R,x,lson);if(R>mid)sum+=query(L,R,x,rson);return sum;}int tmp[MAXN];int solve(int L,int R,int k,int n){int l=1,r=n,mid;while(l<=r){mid=(l+r)>>1;if(query(L,R,tmp[mid],1,n,1) >= k)r=mid-1;elsel=mid+1;}return tmp[r+1];}int main(){int n,m,l,r,k;int T;cin>>T;while(T--){cin>>n>>m;for(int i=1;i<=n;i++)scanf("%d",a+i),tmp[i]=a[i];build(1,n,1);sort(tmp+1,tmp+n+1);while(m--){scanf("%d%d%d",&l,&r,&k);printf("%d\n",solve(l,r,k,n));}for(int i=0;i<MAXN*4;i++)tree[i].clear();}}
阅读全文
0 0
- 块状数组+归并树学习 poj2104+hdu2665
- poj2104||hdu2665 归并树|划分树
- poj2104 hdu2665 划分树
- HDU2665 POJ2104 K-th Number(主席树)
- POJ2104 hdu2665 主席树入门 Kth-number
- POJ2104 归并树
- HDU2665 Kth number 【归并树】
- 可持久化数据结构之线段树 hdu2665 poj2104
- hdu2665 poj2104 可持久化数据结构之线段树
- poj2104&HDU2665 K-th number
- POJ2104 K-th Number 【归并树】
- 【poj2104】K-th Number 归并树
- [POJ2104/HDU2665]Kth Number-主席树-可持久化线段树
- hdu2665/poj2104;poj2761 区间第k小 函数式线段树
- 主席树学习笔记(poj2104)
- 块状数组
- poj 2887 块状数组/线段树
- HDU2665之划分树
- C语言感悟之const
- linux的基本操作
- UTC
- 在JAVAWeb开发中遇到的问题汇总
- Android6.0通讯录权限问题
- 块状数组+归并树学习 poj2104+hdu2665
- Python获取系统音量
- VARIANT、COleVariant 和_variant_t
- centos下为redis添加service
- 网站敏感词过滤的实现(附敏感词库)
- 转载:彻底解决 error: Unable to find vcvarsall.bat
- Error:com.android.builder.internal.aapt.AaptException: Failed to crunch file D:\my\Android-VideoStre
- Redis常用数据类型介绍、使用场景及其操作命令
- Qt5+mysql windows