Dynamic Rankings(动态区间求第K小模板题:树套树(第二份模板效率更高,见下面截图))
来源:互联网 发布:暴雪降至 知乎 编辑:程序博客网 时间:2024/05/16 14:39
Link:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112
The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.
Your task is to write a program for this computer, which
- Reads N numbers from the input (1 <= N <= 50,000)
- Processes M instructions of the input (1 <= M <= 10,000). These instructions include queryingthe k-th smallest number of a[i], a[i+1], ..., a[j] and change some a[i] to t.
Input
The first line of the input is a single number X (0 < X <= 4), the number of the test cases of the input. Then X blocks each represent a single test case.
The first line of each block contains two integers N and M, representing N numbers and M instruction. It is followed by N lines. The (i+1)-th line represents the number a[i]. Then M lines that is in the following format
Q i j k or
C i t
It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change some a[i] to t, respectively. It is guaranteed that at any time of the operation. Any number a[i] is a non-negative integer that is less than 1,000,000,000.
There're NO breakline between two continuous test cases.
Output
For each querying operation, output one integer to represent the result. (i.e. the k-th smallest number of a[i], a[i+1],..., a[j])
There're NO breakline between two continuous test cases.
Sample Input
2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
3
6
(adviser)
Site: http://zhuzeyuan.hp.infoseek.co.jp/index.files/our_contest_20040619.htm
Author: XIN, Tao
Source: Online Contest of Christopher's Adventure
参考博客:http://blog.csdn.net/d891320478/article/details/8648171
AC code:
#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;#define N 60010#define M 60010#define INF 1000000000char ctrl[M][3];int cnt,n,m;int P[M],Q[M],a[N],b[N],K[M];struct treap{ int key,wei,cnt,size,ch[2];}T[N * 15];int tree[N << 1],nodecnt,root;void init(){ T[0].size = 0; T[0].wei = -INF; nodecnt = root = 0;}int ID(int l,int r){return l + r | l != r;}void update(int x){ T[x].size = T[T[x].ch[0]].size + T[T[x].ch[1]].size + T[x].cnt;}void rotate(int &x,int t){ int y = T[x].ch[t]; T[x].ch[t] = T[y].ch[!t]; T[y].ch[!t] = x; update(x); update(y); x = y;}void insert(int &x,int t){ if (!x){ x = ++ nodecnt; T[x].key = t; T[x].wei = rand(); T[x].cnt = 1; T[x].ch[0] = T[x].ch[1] = 0; }else if (T[x].key == t) T[x].cnt ++; else{ int k = T[x].key < t; insert(T[x].ch[k],t); if (T[x].wei < T[T[x].ch[k]].wei) rotate(x,k); } update(x);}void erase(int &x,int t){ if (T[x].key == t){ if (T[x].cnt == 1){ if (!T[x].ch[0] && !T[x].ch[1]) { x = 0;return; } rotate(x,T[T[x].ch[0]].wei < T[T[x].ch[1]].wei); erase(x,t); }else T[x].cnt --; }else erase(T[x].ch[T[x].key < t],t); update(x);}int select(int x,int t){ if (!x) return 0; if (T[x].key > t) return select(T[x].ch[0],t); return T[x].cnt + T[T[x].ch[0]].size + select(T[x].ch[1],t);}void treeins(int l,int r,int i,int x){ insert(tree[ID(l,r)],x); if (l == r) return; int m = l + r >> 1; if (i <= m) treeins(l,m,i,x); else treeins(m + 1,r,i,x);}void treedel(int l,int r,int i,int x){ erase(tree[ID(l,r)],x); if (l == r) return; int m = l + r >> 1; if (i <= m) treedel(l,m,i,x); else treedel(m + 1,r,i,x);}int query(int l,int r,int x,int y,int t){ if (l == r) return l; int m = l + r >> 1; int ans = select(tree[ID(l,m)],y) - select(tree[ID(l,m)],x); if (ans >= t) return query(l,m,x,y,t); return query(m + 1,r,x,y,t - ans);}int main(){ //freopen("in.txt","r",stdin); int Times; int cas; scanf("%d",&cas); while(cas--){ scanf("%d%d",&n,&m); memset(tree,0,sizeof tree); init(); cnt = 0; for (int i = 1;i <= n;i ++) scanf("%d",&a[i]),b[++ cnt] = a[i]; for (int i = 1;i <= m;i ++){ scanf("%s%d%d",ctrl[i],&P[i],&Q[i]); if (ctrl[i][0] == 'Q') scanf("%d",&K[i]); else b[++ cnt] = Q[i]; } sort(b + 1,b + 1 + cnt); cnt = unique(b + 1,b + 1 + cnt) - b - 1; for (int i = 1;i <= n;i ++) { a[i] = lower_bound(b + 1,b + 1 + cnt,a[i]) - b; treeins(1,cnt,a[i],i); } for (int i = 1;i <= m;i ++){ if (ctrl[i][0] == 'Q'){ int id = query(1,cnt,P[i] - 1,Q[i],K[i]); printf("%d\n",b[id]); }else{ treedel(1,cnt,a[P[i]],P[i]); a[P[i]] = lower_bound(b + 1,b + 1 + cnt,Q[i]) - b; treeins(1,cnt,a[P[i]],P[i]); } } } return 0;}
附上别人较简化的代码版本(通过加二分分治优化):
该代码来自博客:http://blog.csdn.net/firenet1/article/details/47858071
AC code:
#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<vector>using namespace std;#define maxn 300007int tree[maxn];void add(int p,int n){ for(;p<maxn;p+=p&(-p)) tree[p]+=n;}int query(int p){ int ans = 0; for(;p>0;p-=p&(-p)) ans += tree[p]; return ans;}struct Node{ int l,r,k,ty,ans;};Node p[maxn];int id1[maxn],id2[maxn];void CDQ(int L,int R,int low,int high){ if(R < L) return ; if(low == high ){ for(;L<=R;L++){ p[id1[L]].ans = low; } return ; } int mid = (low+high)/2,l=L,r=R,k,u; for(int i = L;i <= R; i++){ u = id1[i]; if(p[u].ty == 2){ k = query(p[u].r) - query(p[u].l-1); if(k >= p[u].k) id2[l++] = u; else { p[u].k -= k; id2[r--] = u; } } else if(p[u].k <= mid){ add(p[u].l,p[u].ty); id2[l++] = u; } else id2[r--] = u; } for(int i = L; i <= R; i++){ u = id1[i]; if(p[u].ty != 2 && p[u].k <= mid) add(p[u].l,-p[u].ty); } for(k=L;k<l;k++) id1[k] = id2[k]; for(r=R;k<=R;k++) id1[k] = id2[r--]; CDQ(L,l-1,low,mid); CDQ(l,R,mid+1,high);}int num[maxn];int main(){ int n,q,t,cnt; memset(tree,0,sizeof(tree)); int cas; scanf("%d",&cas); while(cas--){ scanf("%d%d",&n,&q); for(cnt=0;cnt<n;cnt++){ scanf("%d",&p[cnt].k); p[cnt].ty = 1; p[cnt].l = cnt+1; num[cnt+1] = p[cnt].k; } //scanf("%d",&q); int ty,l,v; char ch; for(int i = 0;i < q; i++,cnt++){ scanf("\n%ch",&ch); if(ch=='Q') { p[cnt].ty=2;}else{p[cnt].ty=1;} if(p[cnt].ty == 1){ scanf("%d%d",&l,&v); p[cnt].ty = -1; p[cnt].k = num[l]; p[cnt].l = l; cnt++; num[l] = v; p[cnt].ty = 1; p[cnt].k = v; p[cnt].l = l; } else { scanf("%d%d%d",&p[cnt].l,&p[cnt].r,&p[cnt].k); } } for(int i = 0;i < cnt; i++) id1[i] = i; CDQ(0,cnt-1,0,1000000000); for(int i = 0;i < cnt; i++){ if(p[i].ty == 2) printf("%d\n",p[i].ans); } } return 0;}
两份代码比较,显然第二份(后提交的那份)更优:
Run IDSubmit TimeJudge StatusPro.IDExe.TimeExe.MemoryCode Len.LanguageAuthor146888612015-08-29 23:02:59Accepted54121918MS11248K2440 BG++落纸云烟146884572015-08-29 21:58:02Accepted54124414MS83288K3251 BG++落纸云烟- Dynamic Rankings(动态区间求第K小模板题:树套树(第二份模板效率更高,见下面截图))
- ZOJ 2112 Dynamic Rankings (动态区间第K大) (线段树套SBT+二分)
- ZOJ 2112 Dynamic Rankings(动态求区间第k大+整体二分)
- ZOJ 2112 Dynamic Rankings(线段树套treap求动态第K大)
- zoj2112 Dynamic Rankings 单点修改区间第k小
- ZOJ 2112 Dynamic Rankings 动态区间第k大 分块
- CRB and Queries(动态区间求第k小数模板题:线段树套平衡树)
- ZOJ 2112 Dynamic Rankings 树状数组套主席树 单点修改求动态区间第K大
- BZOJ 1901 Zju 2112 Dynamic Rankings 动态维护第k小 树套树
- ZOJ 2112 Dynamic Rankings (主席树+单点修改,询问区间第K值)
- ZOJ 2112 & BZOJ 1901 Dynamic Rankings(主席树 单点更新 区间第K大)
- 主席树模板 区间第k小
- 【主席树】 ZOJ 2112 Dynamic Rankings 区间第k小值
- ZOJ 1112 Dynamic Rankings【动态区间第K大,整体二分】
- bzoj 1901 Zju2112 Dynamic Rankings(动态区间第k大,主席树)
- ZOJ 2112 Dynamic Rankings(主席树-动态第k大)
- ZOJ 2112 Dynamic Rankings (动态第k大,树状数组套主席树)★★
- ZOJ 2112 Dynamic Rankings (动态第k大,树状数组套主席树)
- HDU 1018 Big Number(斯特林公式)
- Set Difference(所有子集的最值差)
- 黑马程序员——java基础——正则表达式
- autohotkey快捷键显示隐藏文件和文件扩展名
- UIday04_zy:容器视图控制器练习
- Dynamic Rankings(动态区间求第K小模板题:树套树(第二份模板效率更高,见下面截图))
- 题目:二叉树的锯齿形层次遍历
- 转:JSON字符串还原成JS原生值
- 学习《算法导论》第六章 堆排序 总结
- 使用SOCK_RAW构建全网广播包
- 题目:交叉字符串
- Poj.1113 Wall【凸包】 2015/08/29
- 面向对象的优缺点
- 题目:交错正负数