poj 2104 K-th Number(主席树 视频)

K-th Number

题意:

给你一些数,让你求一个区间内,第k大的数是多少。

题解:

主席树第一题,看的qsc视频写的,戳戳戳
学到了unique函数,他的作用是:把相邻的重复的放到后面,返回值是放后面的第一个的迭代器。 故使用之前要排序,之后在用erase删除后面重复的,便可达到去重的目的,之后就可以离散化了。

代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
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)/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()
{
    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
",v[query(1,n,root[x-1],root[y],k)-1]);
    }
}

另一种写法:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100001;
struct Node{
    int ls,rs;
    int cnt;
}tr[maxn*20];
int cur,rt[maxn];
void init(){
    cur=0;
}
inline void push_up(int o){
    tr[o].cnt=tr[tr[o].ls].cnt+tr[tr[o].rs].cnt;
}
int build(int l,int r){
    int k=cur++;
    if (l==r) {
        tr[k].cnt=0;
        return k;
    }
    int mid=(l+r)>>1;
    tr[k].ls=build(l,mid);
    tr[k].rs=build(mid+1,r);
    push_up(k);
    return k;
}
int update(int o,int l,int r,int pos,int val){
    int k=cur++;
    tr[k]=tr[o];
    if (l==pos&&r==pos){
        tr[k].cnt+=val;
        return k;
    }
    int mid=(l+r)>>1;
    if (pos<=mid) tr[k].ls=update(tr[o].ls,l,mid,pos,val);
    else tr[k].rs=update(tr[o].rs,mid+1,r,pos,val);
    push_up(k);
    return k;
}
int query(int l,int r,int o,int v,int kth){
    if (l==r) return l;
    int mid=(l+r)>>1;
    int res=tr[tr[v].ls].cnt-tr[tr[o].ls].cnt;
    if (kth<=res) return query(l,mid,tr[o].ls,tr[v].ls,kth);
    else return query(mid+1,r,tr[o].rs,tr[v].rs,kth-res);
}
int b[maxn];
int sortb[maxn];
int main()
{
    int n,m;
    int T;
    while (~scanf("%d%d",&n,&m)){
        init();
        for (int i=1;i<=n;i++){
            scanf("%d",&b[i]);
            sortb[i]=b[i];
        }
        sort(sortb+1,sortb+1+n);
        int cnt=1;
        for (int i=2;i<=n;i++){
            if (sortb[i]!=sortb[cnt]){
                sortb[++cnt]=sortb[i];
            }
        }
        rt[0]=build(1,cnt);
        for (int i=1;i<=n;i++){
            int p=lower_bound(sortb+1,sortb+cnt+1,b[i])-sortb;
            rt[i]=update(rt[i-1],1,cnt,p,1);
        }
        for (int i=0;i<m;i++){
            int a,b,k;
            scanf("%d%d%d",&a,&b,&k);
            int idx=query(1,cnt,rt[a-1],rt[b],k);
            printf("%d
",sortb[idx]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/s1124yy/p/5716769.html