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次投喂中吃到食物的狮子的觅食能力值。

样例1

样例输入1[复制]

7 2
1 5 2 6 3 7 4
1 5 3
2 7 1

样例输出1[复制]

3
2

限制

各个测试点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
", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Yumesenya/p/6219552.html