POJ2104 ---(区间第K 大)
2016-07-19 13:40
363 查看
学习划分树和主席树练得模板题。
目前只会划分树和主席树了。
题目 :
就是区间第K 大了。
目前只会划分树和主席树了。
Code:
/* 划分树 //#include <bits/stdc++.h> #include <iostream> #include <algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int maxn = 100000 +69; int tree[30][maxn]; //记录树第dep层序列 int sorted[maxn]; //原始序列排序后 int toleft[30][maxn]; //记录树第dep层 前 i 个有多少进入左区间。 void Build(int l, int r, int dep) { if(l ==r) return ; int mid = (l + r) >> 1; int same = mid -l+1; for(int i = l; i <= r; ++i) if(tree[dep][i] < sorted[mid]) same--; int lpos = l; int rpos = mid + 1; for(int i = l; i <= r; ++i) { if(tree[dep][i] < sorted[mid]) tree[dep+1][lpos++] = tree[dep][i]; else if (tree[dep][i] == sorted[mid] && same > 0) tree[dep+1][lpos++] = tree[dep][i], same--; else tree[dep+1][rpos++] = tree[dep][i]; toleft[dep][i] = toleft[dep][l-1] + lpos -l; } Build(l, mid, dep+1); Build(mid+1,r,dep+1); } int query(int L, int R, int l,int r,int dep, int k) { if(l == r) return tree[dep][l]; int mid = (L+R)>>1; int cnt = toleft[dep][r] - toleft[dep][l-1]; //区间有多少数进入左区间 if(cnt >= k) { //递归左树 int newl = L + toleft[dep][l-1]-toleft[dep][L-1]; int newr = newl + cnt - 1; return query(L,mid, newl, newr, dep+1, k); } else { //递归右树 int newr = r + toleft[dep][R] - toleft[dep][r]; int newl = newr - (r-l-cnt); return query(mid+1, R, newl, newr, dep+1,k-cnt); } } int main() { ios::sync_with_stdio(false); int n, m; while(cin >> n >> m) { for(int i = 1; i <= n; ++i) { cin >> tree[0][i]; sorted[i] = tree[0][i]; } sort(sorted+1, sorted+n+1); Build(1,n,0); while(m--) { int l, r, k; cin >> l >> r >> k; cout << query(1,n,l,r,0,k) << endl; } } return 0; } */ // 主席树, 动态的话就套个树状数组可以了。 #include <iostream> #include <algorithm> using namespace std; const int maxn = 100000 + 131; struct Node { int lpos, rpos; int w; Node() { lpos = rpos = w = 0; } }; Node T[maxn * 30]; int a[maxn], b[maxn], p[maxn], root[maxn], sz; bool cmp(int i, int j) { return a[i] < a[j]; } int n, m; void Insert(int &i, int l, int r,int x) { T[++sz] = T[i]; i = sz; T[i].w++; if(l == r) return ; int m = (l + r) >> 1; if(x <= m) Insert(T[i].lpos,l,m,x); else Insert(T[i].rpos, m+1,r,x); } int Query(int i, int j, int l,int r,int k) { if(l == r) return l; int t = T[T[j].lpos].w - T[T[i].lpos].w; int m = (l + r) >> 1; if(t >= k) return Query(T[i].lpos, T[j].lpos,l,m,k); else return Query(T[i].rpos,T[j].rpos,m+1,r,k-t); } int main() { ios::sync_with_stdio(false); while(cin >> n >> m) { root[0] = 0; for(int i = 1; i <= n; ++i) { cin >> a[i]; p[i] = i; } sort(p+1,p+1+n,cmp); for(int i = 1; i <= n; ++i) b[p[i]] = i; sz = 0; for(int i = 1; i <= n; ++i) { root[i] = root[i-1]; Insert(root[i],1,n,b[i]); } while(m--) { int l, r, k; cin >> l >> r >> k; int t = Query(root[l-1],root[r],1,n,k); cout << a[p[t]] <<endl; } } return 0; }
相关文章推荐
- [BZOJ2006][NOI2010][RMQ/主席树][二叉堆]超级钢琴
- BZOJ 2588 Count On a Tree 【LCA】【主席树】
- bzoj 2588 Spoj 10628. Count on a tree
- 主席树(可持久化线段树)入门专题
- Bzoj4556: [Tjoi2016&Heoi2016]字符串
- Kth number (HDU_2665) 划分树
- K-th Number (POJ_2104) 划分树
- BZOJ3209 花神的嘲讽计划I
- POJ 2104 K-th Number
- SPOJ COT 10628 Count on a tree
- ZOJ 2112 Dynamic Rankings
- HDU 4417 Super Mario
- HDU 4348 To the moon
- Codeforces 587C Duff in the Army
- bzoj-3123 森林
- poj 2104 K-th Number (主席树学习第一弹)
- hdu 4605 Magic Ball Game(主席树学习第二弹)
- hdu 4866 Shooting(主席树学习第三弹)
- hdu 3727 Jewel(主席树学习第四弹)
- HDU 2665 Kth number(划分树)