题目背景
这是个非常经典的主席树入门题——静态区间第K小
数据已经过加强,请使用主席树。同时请注意常数优化
题目描述
如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值。
输入格式
第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。
第二行包含N个整数,表示这个序列各项的数字。
接下来M行每行包含三个整数l, r, kl,r,k , 表示查询区间[l, r][l,r]内的第k小值。
输出格式
输出包含k行,每行1个整数,依次表示每一次查询的结果
输入输出样例
输入 #1
5 5 25957 6405 15770 26287 26465 2 2 1 3 4 1 4 5 1 1 2 2 4 4 1
输出 #1
6405 15770 26287 25957 26287
样例数据说明:
N=5,数列长度为5,数列从第一项开始依次为[25957, 6405, 15770, 26287, 26465 ]
第一次查询为[2, 2]区间内的第一小值,即为6405
第二次查询为[3, 4]区间内的第一小值,即为15770
第三次查询为[4, 5]区间内的第一小值,即为26287
第四次查询为[1, 2]区间内的第二小值,即为25957
第五次查询为[4, 4]区间内的第一小值,即为26287
分析:
模板题???去TM的。。。一道模板题调我一晚上。。。(除了treap,树剖外调的时间最长一道题目)
PS:目前调(不含第一遍写的时间)的时间最久的(不看题解):
1.猪国杀??? 1个月 (还没写好。。。)
2.treap 4个小时
2.树剖 4个小时
4.主席树 3个小时
4.有机化学之神之偶尔会作弊 3个小时(神题。。。结合多种算法。。)
6.网络流 2.5个小时
7.字符串的展开 2个小时
7.牛绣花(你TM试试自己推这题的公式。。。) 2个小时
9.洛谷P1962 斐波那契数列(哼哼,你自己看看数据范围) 1.5小时
9.[AHOI2009]中国象棋(你试试这题递推方程。。。) 1.5小时
CODE:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const int M=30000005; 6 int p[M],a[M]; 7 int n,m; 8 int rt[M],tot; 9 struct tree{ 10 int son[2],size; 11 }node[M]; 12 void build (int &rt,int l,int r){ 13 rt=++tot; 14 int mid=(l+r)>>1; 15 if (!(l^r)) return ; 16 build (node[rt].son[0],l,mid); 17 build (node[rt].son[1],mid+1,r); 18 } 19 int bsearch(int k){ 20 int l=1,r=m; 21 while (l<=r){ 22 int mid=(l+r)>>1; 23 if (p[mid]==k) return mid; 24 if (p[mid]<k) l=mid+1; 25 else r=mid-1; 26 } 27 return l; 28 } 29 void np(int &rt,int lst,int l,int r,int val){ 30 node[rt=++tot]=node[lst]; 31 ++node[rt].size; 32 int mid=(l+r)>>1; 33 if (!(l^r)) return ; 34 if (val<=mid) np(node[rt].son[0],node[lst].son[0],l,mid,val); 35 else np(node[rt].son[1],node[lst].son[1],mid+1,r,val); 36 } 37 int query(int rt1,int rt2,int l,int r,int k){ 38 int mid=(l+r)>>1; 39 if (!(l^r)) return p[l]; 40 if(node[node[rt2].son[0]].size-node[node[rt1].son[0]].size>=k) 41 return query(node[rt1].son[0],node[rt2].son[0],l,mid,k); 42 else 43 return query(node[rt1].son[1], node[rt2].son[1],mid+1,r,k-node[node[rt2].son[0]].size+node[node[rt1].son[0]].size); 44 } 45 int read(){ 46 int res=0; 47 int f=1; 48 char c=getchar(); 49 while (c>'9'||c<'0') { 50 if (c=='-') f=-1; 51 c=getchar(); 52 } 53 while (c<='9'&&c>='0') { 54 res=(res<<3)+(res<<1)+c-'0'; 55 c=getchar(); 56 } 57 return res*f; 58 } 59 int main(){ 60 scanf ("%d",&n); 61 int mm; 62 scanf ("%d",&mm); 63 for (int i=1;i<=n;i++) 64 a[i]=read(),p[i]=a[i]; 65 sort(p+1,p+n+1); 66 m=unique(p+1,p+n+1)-p-1; 67 build(rt[0],1,m); 68 //cout<<m<<endl; 69 /*for (int i=1;i<=m;i++) 70 cout<<p[i]<<endl;*/ 71 for (int i=1;i<=n;i++){ 72 //cout<<a[i]<<" "<<bsearch(a[i])<<endl; 73 np(rt[i],rt[i-1],1,m,bsearch(a[i])); 74 } 75 while (mm--){ 76 int i,j,l; 77 i=read(),j=read(),l=read(); 78 printf("%d ",query(rt[i-1],rt[j],1,m,l)); 79 } 80 //system("pause"); 81 return 0; 82 }