POJ 2104 Interval k-th largest (Chairman of the tree)

Topic links: http://poj.org/problem?id=2104

Title effect: as well as a sequence number of a given n, m operations, each operation comprising l, r, k, find the interval [l, r] k-th largest

Problem-solving ideas: the maximum segment tree can only maintain the minimum sequence, consider the establishment of a segment tree for each input sequence prefix, that contains n pieces of tree line, this will certainly burst memory. Two adjacent segments of the same tree, in fact, there are many different probably log n nodes, we opened a new log n nodes on it. Each sum is stored node number of the current node number appears, for the interval [L, r], r pieces we use the first segment tree subtracting l-1 pieces of segment tree is obtained [L, r] interval the number of times each node appears, starting with its left sub-tree began to look for to determine whether the left sub-tree node number is greater than the sum equal to k, if k greater than or equal to find a large tree on the left sub k, or find the first right subtree k-sum large.

Code:

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
using namespace std;
const int maxn=1e5+6;
int n,m,cnt,root[maxn],a[maxn],x,y,k;
struct node{
    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(mid>=pos) 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>>1;
    int sum=T[T[y].l].sum-T[T[x].l].sum;
    if(sum>=k) return query(l,mid,T[x].l,T[y].l,k);
    else return query(mid+1,r,T[x].r,T[y].r,k-sum);
}
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;
}

 

Guess you like

Origin www.cnblogs.com/zjl192628928/p/11230261.html