2018-07-22 20:35:11
终于有了自己的主席书板子 先保存下来 明天写总结 挖坑++
#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; const int maxn = 1e5+10; int n , m; int cnt; struct node { int L , R; ///该节点的左右节点 int sum; ///该节点所管辖区域内数字的个数 node() { sum = 0; } } Tree[maxn*20]; struct value { int x; int id; } val[maxn]; ///离散化 bool cmp(value a, value b) { return a.x < b.x; } int root[maxn]; ///多颗线段树的根节点 int rank[maxn]; ///原数组离散之后的数组 void init() { cnt = 1; root[0] =0; Tree[0].L = Tree[0].R = Tree[0].sum = 0; ///初始化建立一个空节点 } void input() { for(int i=1; i<=n; i++) { scanf("%d" , &val[i].x); val[i].id = i; } } void update(int num , int &rt , int l , int r) { Tree[cnt++] = Tree[rt]; rt = cnt-1; Tree[rt].sum++; ///增加了一个数字 if(l == r) return; int mid = (l+r)/2; if(num <= mid) update(num , Tree[rt].L , l , mid); else update(num , Tree[rt].R , mid+1 , r); } int query(int i , int j , int k , int l , int r) { if(l == r) return l; int d = Tree[Tree[j].L].sum-Tree[Tree[i].L].sum; int mid = (l+r)/2; if(k <= d) return query(Tree[i].L , Tree[j].L , k , l , mid); else return query(Tree[i].R , Tree[j].R , k-d , mid+1 , r); } void solve() { int l , r , k; for(int i=1; i<=m; i++) { scanf("%d%d%d" , &l , &r , &k); printf("%d\n" , val[query(root[l-1] , root[r] , k , 1 , n)].x); } } int main() { while( scanf("%d%d" , &n , &m) != EOF ) { input(); sort(val+1 , val+1+n , cmp); for(int i=1; i<=n; i++) { rank[val[i].id] = i; } ///离散化结束 init(); for(int i=1; i<=n; i++) { root[i] = root[i-1]; update(rank[i] , root[i] , 1 , n); } solve(); } return 0; }