【主席树 求区间第k大】poj 2104 K-th Number

来源:互联网 发布:cv 知乎 编辑:程序博客网 时间:2024/05/22 05:34

Link:http://poj.org/problem?id=2104

离散化+保存历史版本的线段树,线段树结点代表的意思是区间(值域)数的个数

#include <cstdio>#include <vector>#include <algorithm>using namespace std;typedef long long LL;//#pragma comment(linker, "/STACK:102400000,102400000")const int N = 1e5+5;int n,m,cnt,root[N],a[N];struct Node{ int l,r,sum; }T[N*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)/2;    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)/2;    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(){//    cnt = 0;    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]));    int x,y,k;    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;}


阅读全文
0 0
原创粉丝点击