1. 程式人生 > >POJ2104主席樹模板題

POJ2104主席樹模板題

root contains mem void con gin bsp 情況 scan

完成新成就——B站上看了算法https://www.bilibili.com/video/av4619406/?from=search&seid=17909472848554781180#page=2

K-th Number
Time Limit: 20000MS Memory Limit: 65536K
Total Submissions: 60158 Accepted: 21054
Case Time Limit: 2000MS

Description

You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment.
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?"
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

Input

The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000).
The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given.
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).

Output

For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

Sample Input

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

Sample Output

5
6
3

Hint

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed. 題意很簡單,求n個數,m個操作,以及區間第K大數。 我們考慮1個算法,建n顆權值線段樹,第i顆表示前i個數中的所有取值個數(離散化一下),這樣我們可以用第r棵子樹減去第l-1顆子樹,得到l~r中各個值的取值情況。這是我們就可以二分第k大值在哪個區間了,如果左邊子數的size比k不小於的話往左找,否則往右。 關於多棵樹的問題就交給主席樹了。 順便空間開40倍
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#define maxn 100006
using namespace std;
int n,m,cnt,a[maxn],root[maxn],x,y,k;
struct note{
    int l,r,sum;
}T[maxn*40];
vector<int> v;
int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}

void update(int l,int r,int &x,int y,int pos)
{
    T[++cnt]=T[y];T[cnt].sum++;x=cnt;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(pos<=mid) update(l,mid,T[x].l,T[y].l,pos);else
    update(mid+1,r,T[x].r,T[y].r,pos);
}
int query(int l,int r,int x,int y,int k)
{
    if(l==r) return l;
    int mid=(l+r)/2;
    int sum=T[T[y].l].sum-T[T[x].l].sum;
    if(sum<k)return query(mid+1,r,T[x].r,T[y].r,k-sum);else
    return query(l,mid,T[x].l,T[y].l,k);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),v.push_back(a[i]);
    sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
    for(int i=1;i<=n;i++) update(1,n,root[i],root[i-1],getid(a[i]));
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&x,&y,&k);
        printf("%d\n",v[query(1,n,root[x-1],root[y],k)-1]);
    }
    return 0;     
 } 

POJ2104主席樹模板題