【SPOJ KQUERY】【HDU 4417】静态区间rank查询
来源:互联网 发布:信鸽种鸽出售淘宝网 编辑:程序博客网 时间:2024/05/16 05:37
SPOJ KQUERY:给一个数列,查询x在区间l,r上有多少数字>x
HDU4417:给一个数列,查询x在区间l,r上有多少数字<=x
离线树状数组,在线主席树,都可以做到logn复杂度的查询,不过主席树的常数超级大,SPOJ那题打死都是TLE,不能直视~
树状数组做法是先对所有询问按x从小到大排序,然后把原数列里<=x的数按下标加入树状数组,每次查询区间lr的区间和。
代码如下:
SPOJ KQUERY
int z[NN],a[NN],b[NN],lb;int u[MM],v[MM],w[MM],id[MM],ans[MM];int n,m;void update(int x){while (x<=n){z[x]++;x+=lowbit(x);}}int sum(int x){int ans=0;while (x>0){ans+=z[x];x-=lowbit(x);}return ans;}int cmp(int i,int j){return w[i]<w[j];}int cmp2(int i,int j){return a[i]<a[j];}int main(){n=fastget();for(int i=1;i<=n;i++)a[b[i]=i]=fastget();m=fastget();for(int i=1;i<=m;i++){u[i]=fastget();v[i]=fastget();w[i]=fastget();id[i]=i;}sort(id+1,id+1+m,cmp);sort(b+1,b+1+n,cmp2);int j=1;for(int i=1;i<=m;i++){for(;j<=n;j++)if(a[b[j]]<=w[id[i]]) update(b[j]);else break;ans[id[i]]=v[id[i]]-u[id[i]]+1-(sum(v[id[i]])-sum(u[id[i]]-1));}for(int i=1;i<=m;i++)fastput(ans[i]);return 0;}
主席树做法:
数列离散化,按权值建线段树,建树方式和POJ2104一样,查询的时候如果区间的mid>=x就查询左子树,否则左子树和加上右子树的查询结果。
int a[NN],b[NN],lb,n,m;struct segmenttree{ int l,r,s;}tree[NN*25];int node;int root[NN];int search(int x){ int l=0,r=lb,mid; while (l<r) { mid=l+r+1>>1; if(b[mid]<=x) l=mid; else r=mid-1; } return l;}int build(int l,int r){ int k=++node; tree[k].s=0; if(l==r) return k; int m=l+r>>1; if(l<=m) tree[k].l=build(l,m); if(r>m) tree[k].r=build(m+1,r); return k;}int change(int rt,int l,int r,int x){ int k=++node,root=k,mid; tree[k]=tree[rt]; tree[k].s++; while (l<r) { mid=l+r>>1; if(x<=mid) { rt=tree[rt].l; tree[k].l=++node; k=node; tree[k]=tree[rt]; tree[k].s++; r=mid; } else { rt=tree[rt].r; tree[k].r=++node; k=node; tree[k]=tree[rt]; tree[k].s++; l=mid+1; } } return root;}int query(int L,int R,int l,int r,int x){ int mid,ans=0; while (l<r) { mid=l+r>>1; if(mid>=x) { r=mid; L=tree[L].l; R=tree[R].l; } else { l=mid+1; ans+=tree[tree[R].l].s-tree[tree[L].l].s; L=tree[L].r; R=tree[R].r; } } if(l==r) { if(x<l) return 0; else return ans+tree[R].s-tree[L].s; }}int u,v,w,i;int main(){ int tt=fastget(); for(int cs=1;cs<=tt;cs++) { n=fastget(); m=fastget(); for(i=1;i<=n;i++) b[i]=a[i]=fastget(); lb=1; sort(b+1,b+1+n); for(i=2;i<=n;i++) if(b[i]!=b[lb]) b[++lb]=b[i]; node=0; root[0]=build(1,lb); for(i=1;i<=n;i++) root[i]=change(root[i-1],1,lb,search(a[i])); printf("Case %d:\n",cs); while (m--) { u=fastget(),v=fastget(),w=fastget(); u++; v++; w=search(w); if(w==0) fastput(0); else fastput(query(root[u-1],root[v],1,lb,w)); } } return 0;}
- 【SPOJ KQUERY】【HDU 4417】静态区间rank查询
- HDU 4417-树状数组求区间rank查询/主席树区间rank查询
- Impossible Boss+SPOJ+线段树区间更新、区间查询
- SPOJ COT2 树上的莫队算法,树上区间查询
- !SPOJ 1043 多次查询区间最大连续和-线段树
- hdu 3911 区间合并+区间查询
- Rank HDU
- Rank HDU
- RMQ静态区间最值查询
- [SPOJ PUTNIK]区间DP
- spoj K-th Number (classic! 区间静态第k大)
- hdu - 4325- Flowers - 区间更新,单点查询
- hdu 1566 BIT 区间更新单点查询
- HDU 1540 线段树(区间查询)
- HDU 3911 线段树区间染色 区间查询
- HDU 3397 线段树区间染色 区间查询
- HDU 3954 区间更新区间查询 打怪升级
- hdu 5023(线段树区间更新+区间查询)
- ubuntu and windows 7 setting two displays
- 黑话管理:偶像
- plsql developer导出csv乱码问题
- IO流4及总结
- Hadoop2.0 配置详解
- 【SPOJ KQUERY】【HDU 4417】静态区间rank查询
- 数据库有用网站
- ZOJ 3689 D Digging
- Android屏幕长按事件(自定义时间长短)
- 动态规划-最长公共子串问题的实现
- 10 ways to present yourself more professionally
- hibernate缓存:一级缓存和二级缓存
- 动态规划-导弹拦截
- 【easyUI】$(function() {});