【模板】可持久化线段树[主席树]

P3834 【模板】可持久化线段树 1(主席树)

询问区间第k大 照着学长模板打的

资料       

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,M=100000+5,inf=0x3f3f3f3f;
int n,m,a[N],w[N];
int tl,tot=0,rt[N];
template<class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

struct tree{
    int l,r,sum;
}t[N*50];

void pup(int o){
    t[o].sum=t[t[o].l].sum+t[t[o].r].sum;
}
void update(int l,int r,int &o,int pre,int k){
    o=++tot;
    if(l==r){t[o].sum=t[pre].sum+1;return;}
    int mid=l+r>>1;
    if(k<=mid) update(l,mid,t[o].l,t[pre].l,k),t[o].r=t[pre].r;
    else update(mid+1,r,t[o].r,t[pre].r,k),t[o].l=t[pre].l;
    pup(o);
}

int query(int l,int r,int x,int y,int k){
    if(l==r) return l;
    int mid=l+r>>1,ss=t[t[y].l].sum-t[t[x].l].sum;
    if(ss>=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-ss);
}

int main(){
    rd(n),rd(m);
    for(int i=1;i<=n;++i) rd(a[i]),w[i]=a[i];
    sort(a+1,a+n+1);
    tl=unique(a+1,a+n+1)-a-1;
    for(int i=1;i<=n;++i){
        w[i]=lower_bound(a+1,a+tl+1,w[i])-a;
        update(1,tl,rt[i],rt[i-1],w[i]);
    }
    for(int i=1,l,r,k;i<=m;++i){
        rd(l),rd(r),rd(k);
        printf("%d\n",a[query(1,tl,rt[l-1],rt[r],k)]);
    }
    return 0;
} 

QAQ居然和我看的那个版本不一样

/*  主席树求区间第K大模板:
    模板特殊说明:
    每棵树是维护从1开始到cnt的下标信息
*/
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#define ll long long
#define go(i,x,a) for(int i=a;i<x;i++)
#define INF 0x7f7f7f7f
using namespace std;
 
const int maxn=1e5+5;
int T,n,m,tot,a[maxn],b[maxn],cnt,roots[maxn];
struct N { int ls, rs, w; } tree[30 * maxn];
 
int build_tree(int l, int r) {  
    int newnode = tot++;
    tree[newnode].w = 0;
    if (l != r) {
        int mid = (l + r) / 2;
        tree[newnode].ls = build_tree(l, mid);
        tree[newnode].rs = build_tree(mid + 1, r);
    }
    return newnode;
}
 
int updata(int rt, int pos, int val) {  
    int newnode = tot++, tmp = newnode;
    tree[newnode].w = tree[rt].w + val;
    int l = 1, r = cnt;
    while (l < r) {
        int mid = (l + r) / 2;
        if (pos <= mid) {
            tree[newnode].ls = tot++;
            tree[newnode].rs = tree[rt].rs;
            newnode = tree[newnode].ls;
            rt = tree[rt].ls;
            r = mid;
        }
        else {
            tree[newnode].ls = tree[rt].ls;
            tree[newnode].rs = tot++;
            newnode = tree[newnode].rs;
            rt = tree[rt].rs;
            l = mid + 1;
        }
        tree[newnode].w = tree[rt].w + val;
    }
    return tmp;
}
 
int query(int rt1, int rt2, int k) {  
    int l = 1, r = cnt;
    while (l < r) {
        int mid = (l + r) / 2;
        int tmp = tree[tree[rt2].ls].w - tree[tree[rt1].ls].w;
        if (tmp >= k) {
            rt1 = tree[rt1].ls;
            rt2 = tree[rt2].ls;
            r = mid;
        }
        else {
            k -= tmp;
            rt1 = tree[rt1].rs;
            rt2 = tree[rt2].rs;
            l = mid + 1;
        }
    }
    return l;
}
 
int main() {
    scanf("%d", &T);
    while (T--) {  
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            b[i - 1] = a[i];
        }
        sort(b, b + n);
        cnt = unique(b, b + n) - b;    
        tot = 0;
        roots[0] = build_tree(1, cnt);
        for (int i = 1; i <= n; i++) {
            int tmp = (int)(lower_bound(b, b + cnt, a[i]) - b) + 1;
            roots[i] = updata(roots[i - 1], tmp, 1);   
        }
        int l,r,k;
        for(int i=0;i<m;i++){
            scanf("%d %d %d",&l,&r,&k); 
            int tmp = query(roots[l-1],roots[r],k);
            printf("%d\n",b[tmp - 1]);
        }
    }
    return 0;
}//Faze
学长’s

 

posted @ 2019-07-31 19:57  委屈的咸鱼鱼鱼鱼  阅读(159)  评论(0编辑  收藏  举报