vijos 1081 野生动物园 函数式线段树
描述
cjBBteam拥有一个很大的野生动物园。这个动物园坐落在一个狭长的山谷内,这个区域从南到北被划分成N个区域,每个区域都饲养着一头狮子。这些狮子从北到南编号为1,2,3,…,N。每头狮子都有一个觅食能力值Ai,Ai越小觅食能力越强。饲养员cmdButtons决定对狮子进行M次投喂,每次投喂都选择一个区间[I,J],从中选取觅食能力值第K强的狮子进行投喂。值得注意的是,cmdButtons不愿意对某些区域进行过多的投喂,他认为这样有悖公平。因此cmdButtons的投喂区间是互不包含的。你的任务就是算出每次投喂后,食物被哪头狮子吃掉了。
格式
输入格式
输入第一行有两个数N和M。此后一行有N个数,从南到北描述狮子的觅食能力值。此后M行,每行描述一次投喂。第t+2的三个数I,J,K表示在第t次投喂中,cmdButtons选择了区间[I,J]内觅食能力值第K强的狮子进行投喂。
输出格式
输出有M行,每行一个整数。第i行的整数表示在第i次投喂中吃到食物的狮子的觅食能力值。
限制
各个测试点2s
题意:没有修改,区间查询第k大
思路:裸的主席树。区间第K大及它的各类变种CLJ的《可持续化数据结构研究》分析地很详细了 orz
/** @Date : 2016-12-15-20.55 * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : */ #include<bits/stdc++.h> #define LL long long #define PII pair #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 1e5+20; const double eps = 1e-8; struct yuu { int a, b, sum; int l, r; }tt[N << 5]; int n, m; int rt[N], a[N], ss[N]; int cnt; void build(int a, int b, int &p) { p = ++cnt; tt[p].a = a; tt[p].b = b; if(a == b) return ; int mid = (a + b) >> 1; build(a, mid, tt[p].l); build(mid + 1, b, tt[p].r); } void add(int pre, int &p, int pos) { p = ++cnt; tt[p].l = tt[pre].l; tt[p].r = tt[pre].r; tt[p].a = tt[pre].a; tt[p].b = tt[pre].b; tt[p].sum = tt[pre].sum + 1; int mid = (tt[pre].a + tt[pre].b) >> 1; if(tt[pre].a < tt[pre].b) if(pos <= mid) add(tt[pre].l, tt[p].l, pos); else add(tt[pre].r, tt[p].r, pos); } int query(int pre, int nw, int s) { if(tt[nw].a == tt[nw].b) { return ss[tt[nw].a]; } int t = tt[tt[nw].l].sum - tt[tt[pre].l].sum; if(s <= t) return query(tt[pre].l, tt[nw].l, s); else return query(tt[pre].r, tt[nw].r, s - t); } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) scanf("%d", &a[i]), ss[i] = a[i]; sort(ss + 1, ss + 1 + n); MMF(rt); cnt = 0; build(1, n, rt[0]); for(int i = 1; i <= n; i++) { int pos = lower_bound(ss + 1, ss + 1 + n, a[i]) - ss; add(rt[i - 1], rt[i], pos); } for(int i = 1; i <= m; i++) { int x, y, k; scanf("%d%d%d", &x, &y, &k); int ans = query(rt[x - 1], rt[y], k); printf("%d\n", ans); } return 0; }