POJ 2104 K-th Number
2013-08-10 03:40
507 查看
题意: 询问区间第K小数
解法: 可持久化线段树。每次更新需logn的空间,所以总空间为nlogn。
其实就是把每次的更新操作放在新的空间里,保留下之前的版本。所以具有提供在线查询的功能,似及比离线操作方便,代码简单,反正划分树失业了。。
详细的教程见这里
数据范围较大需离散化。
一开始有尝试类似于trie的New_node写法,用到再申请,省略了建树的过程。实测在POJ慢了62MS,在HDU快34MS。
数据结构真是越来越神奇了额ORZ
下面是省略build过程的写法,其实速度差不多。
解法: 可持久化线段树。每次更新需logn的空间,所以总空间为nlogn。
其实就是把每次的更新操作放在新的空间里,保留下之前的版本。所以具有提供在线查询的功能,似及比离线操作方便,代码简单,反正划分树失业了。。
详细的教程见这里
数据范围较大需离散化。
一开始有尝试类似于trie的New_node写法,用到再申请,省略了建树的过程。实测在POJ慢了62MS,在HDU快34MS。
数据结构真是越来越神奇了额ORZ
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define FOR(i,a,b) for(int i=(a); i<=(b); i++) #define REP(i,a,b) for(int i=(a); i<(b); i++) #define clr(a,b) memset(a,b,sizeof(a)) const int INF = ~0u>>1; const int MAXN = 101000; int num[MAXN]; int san[MAXN]; int head[MAXN],tot; struct SGT { int ls,rs,cnt; }t[MAXN*20]; void build(int l, int r, int &rt) { rt = tot ++; t[rt].cnt = 0; if(l == r) return ; int m = (l+r)>>1; build(l,m,t[rt].ls); build(m+1,r,t[rt].rs); } void pushup(int rt) { t[rt].cnt = t[t[rt].ls].cnt + t[t[rt].rs].cnt; } void update(int bef, int pos, int l, int r, int &rt) { rt = tot ++; if(l == r) { t[rt].cnt = t[bef].cnt + 1; return ; } int m = (l+r)>>1; if(pos <= m) { update(t[bef].ls,pos,l,m,t[rt].ls); t[rt].rs = t[bef].rs; } else { update(t[bef].rs,pos,m+1,r,t[rt].rs); t[rt].ls = t[bef].ls; } pushup(rt); } int query(int bef, int now, int num, int l, int r) { if(l == r) return l; int m = (l+r)>>1; int tt = t[t[now].ls].cnt - t[t[bef].ls].cnt; if(num <= tt) return query(t[bef].ls,t[now].ls,num,l,m); else return query(t[bef].rs,t[now].rs,num-tt,m+1,r); } int main() { int n,m; while(~scanf("%d%d", &n, &m)) { FOR(i,1,n) { scanf("%d", &num[i]); san[i] = num[i]; } int nt; sort(san+1,san+n+1); nt = unique(san+1,san+n+1) - san - 1; FOR(i,1,n) num[i] = lower_bound(san+1,san+nt+1,num[i]) - san; tot = 0; build(1,nt,head[0]); FOR(i,1,n) update(head[i-1],num[i],1,nt,head[i]); int a,b,c; while(m--) { scanf("%d%d%d", &a, &b, &c); int tt = query(head[a-1],head[b],c,1,nt); printf("%d\n", san[tt]); } } return 0; }
下面是省略build过程的写法,其实速度差不多。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define FOR(i,a,b) for(int i=(a); i<=(b); i++) #define REP(i,a,b) for(int i=(a); i<(b); i++) #define clr(a,b) memset(a,b,sizeof(a)) const int INF = ~0u>>1; const int nill = 0; const int MAXN = 101000; int num[MAXN]; int san[MAXN]; int head[MAXN],tot; struct SGT { int ls,rs,cnt; }t[MAXN*20]; int New_node() { t[tot].ls = t[tot].rs = nill; t[tot].cnt = 0; return tot ++; } void pushup(int rt) { t[rt].cnt = t[t[rt].ls].cnt + t[t[rt].rs].cnt; } void update(int bef, int pos, int l, int r, int &rt) { rt = New_node(); if(l == r) { t[rt].cnt = t[bef].cnt + 1; return ; } if(t[bef].ls == nill) t[bef].ls = New_node(); if(t[bef].rs == nill) t[bef].rs = New_node(); int m = (l+r)>>1; if(pos <= m) { update(t[bef].ls,pos,l,m,t[rt].ls); t[rt].rs = t[bef].rs; } else { update(t[bef].rs,pos,m+1,r,t[rt].rs); t[rt].ls = t[bef].ls; } pushup(rt); } int query(int bef, int now, int num, int l, int r) { if(l == r) return l; int m = (l+r)>>1; int tt = t[t[now].ls].cnt - t[t[bef].ls].cnt; if(num <= tt) return query(t[bef].ls,t[now].ls,num,l,m); else return query(t[bef].rs,t[now].rs,num-tt,m+1,r); } int main() { int n,m; while(~scanf("%d%d", &n, &m)) { FOR(i,1,n) { scanf("%d", &num[i]); san[i] = num[i]; } int nt; sort(san+1,san+n+1); nt = unique(san+1,san+n+1) - san - 1; FOR(i,1,n) num[i] = lower_bound(san+1,san+nt+1,num[i]) - san; tot = 0; New_node(); head[0] = New_node(); FOR(i,1,n) update(head[i-1],num[i],1,nt,head[i]); int a,b,c; while(m--) { scanf("%d%d%d", &a, &b, &c); int tt = query(head[a-1],head[b],c,1,nt); printf("%d\n", san[tt]); } } return 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 (主席树模板)
- poj2104 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【模板】(主席树)
- K-th Number (poj 2104 线段树+二分)
- POJ - 2104 K-th Number (求区间第K小)