主席树入门\模板

主席树好难,学了好久才学会,推荐个不错的博客https://blog.csdn.net/ModestCoder_/article/details/90107874 我这边就不赘述了。

 

AcWing 255. 第K小数

经典的主席树入门题

离散化+模板 (👇我的板子)

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map> 
#include <stack>
#include <sstream>
#include <set>
#pragma GCC optimize(2)

//#define int long long
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点,确认思路再敲!!! 

using namespace std;
typedef long long ll;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)

const int N = 1e5 + 5, M = 1e4 + 5, mod = 1e9 + 9, INF = 0x3f3f3f3f;
int n, m;
int a[N];
vector<int> nums;

inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

struct node {
    int l, r;
    int cnt;
}tr[N * 4 + N * 17];

int root[N], idx;

int find(int x) {
    return lower_bound(nums.begin(), nums.end(), x) - nums.begin();
}

int build(int l, int r) {
    int p = ++idx;
    if (l == r) return p;
    int mid = l + r >> 1;
    tr[p].l = build(l, mid);
    tr[p].r = build(mid + 1, r);
    return p;
}

int insert(int p, int l, int r, int x) {
    int q = ++idx;
    tr[q] = tr[p];
    if (l == r) {
        tr[q].cnt++;
        return q;
    }
    int mid = l + r >> 1;
    if (x <= mid) tr[q].l = insert(tr[p].l, l, mid, x);
    else tr[q].r = insert(tr[p].r, mid + 1, r, x);
    tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt;
    return q;
}

int query(int q, int p, int l, int r, int k) {
    if (l == r) return r;
    int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
    int mid = l + r >> 1;
    if (k <= cnt) return query(tr[q].l, tr[p].l, l, mid, k);
    else return query(tr[q].r, tr[p].r, mid + 1, r, k - cnt);
}

int main()
{
    n = read(); m = read();
    for (int i = 1; i <= n; ++i) {
        a[i] = read();
        nums.push_back(a[i]);
    }
    sort(nums.begin(), nums.end());
    nums.erase(unique(nums.begin(), nums.end()), nums.end());

    root[0] = build(0, nums.size() - 1);

    for (int i = 1; i <= n; ++i)
        root[i] = insert(root[i - 1], 0, nums.size() - 1, find(a[i]));

    while (m--) {
        int l, r, k;
        l = read(); r = read(); k = read();
        printf("%d\n", nums[query(root[r], root[l - 1], 0, nums.size() - 1, k)]);
    }
    // system("pause");
    return 0;
}

 

 

 

 

牛客、换个角度思考

原题链接https://ac.nowcoder.com/acm/problem/19427

可以离线下来用树状数组维护,也可以直接上主席树

离线+树状数组:

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <sstream>
#include <set>
#pragma GCC optimize(2)
 
//#define int long long
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点,确认思路再敲!!!
 
using namespace std;
typedef long long ll;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)
 
const int N = 2e5 + 5, M = 2e5 + 5, mod = 1e9 + 9, INF = 0x3f3f3f3f;
int n, m;
pair<int, int>a[N];
ll tr[N];
vector<int> vec[N];
map<pair<int, PII>, ll>q;
 
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
 
struct node {
    int x, l, r, id;
}list[N];
 
bool cmp1(node a, node b) {
    return a.x < b.x;
}
 
bool cmp2(node a, node b) {
    return a.id < b.id;
}
 
int lowbit(int x) {
    return x & -x;
}
 
void add(int x, ll y) {
    for (int i = x; i <= n; i += lowbit(i)) {
        tr[i] += y;
    }
}
 
ll sum(int x)
{
    int ans = 0;
    for (int i = x; i > 0; i -= lowbit(i))
        ans += tr[i];
     
    return ans;
}
 
int main()
{
    n = read(); m = read();
    for (int i = 1; i <= n; ++i) {
        int x; x = read();
        a[i] = {x, i};
    }
    for (int i = 1; i <= m; ++i) {
        list[i].l = read();
        list[i].r = read();
        list[i].x = read();
        list[i].id = i;
    }
    sort(a + 1, a + 1 + n);
    sort(list + 1, list + 1 + m, cmp1);
    ll now = 1;
    for (int i = 1; i <= m; ++i) {
        while (now <= n && a[now].first <= list[i].x) {
            add(a[now].second, 1);
            now++;
        }
        q[mp(list[i].x, mp(list[i].l, list[i].r))] = sum(list[i].r) - sum(list[i].l - 1);
    }
    sort(list + 1, list + 1 + m, cmp2);
    for (int i = 1; i <= m; ++i) {
        printf("%lld\n", q[mp(list[i].x, mp(list[i].l, list[i].r))]);
    }
    // system("pause");
    return 0;
}

 

 

主席树:

直接套模板就行

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map> 
#include <stack>
#include <sstream>
#include <set>
#pragma GCC optimize(2)

//#define int long long
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define pi acos(-1)
#define fi first
#define se second
//你冷静一点,确认思路再敲!!! 

using namespace std;
typedef long long ll;
typedef pair<int, int > PII;
priority_queue< PII, vector<PII>, greater<PII> > que;
stringstream ssin; //  ssin << string   while ( ssin >> int)

const int N = 1e5 + 5, M = 1e4 + 5, mod = 1e9 + 9, INF = 0x3f3f3f3f;
int n, m;
int a[N];
vector<int> nums;

inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}

struct node {
    int l, r;
    int cnt;
}tr[N * 4 + N * 17];

int root[N], idx;

int build(int l, int r) {
    int p = ++idx;
    if (l == r) return p;
    int mid = l + r >> 1;
    tr[p].l = build(l, mid);
    tr[p].r = build(mid + 1, r);
    return p;
}

int insert(int p, int l, int r, int x) {
    int q = ++idx;
    tr[q] = tr[p];
    if (l == r) {
        tr[q].cnt++;
        return q;
    }
    int mid = l + r >> 1;
    if (x <= mid) tr[q].l = insert(tr[p].l, l, mid, x);
    else tr[q].r = insert(tr[p].r, mid + 1, r, x);
    tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt;
    return q;
}

int query(int q, int p, int l, int r, int k) {
    
    if (l == r) return tr[q].cnt - tr[p].cnt;
    int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
    int mid = l + r >> 1;
    if (k <= mid) return query(tr[q].l, tr[p].l, l, mid, k);
    else return cnt + query(tr[q].r, tr[p].r, mid + 1, r, k);
}

int main()
{
    n = read(); m = read();
    for (int i = 1; i <= n; ++i) {
        a[i] = read();
    }

    root[0] = build(0, N);

    for (int i = 1; i <= n; ++i)
        root[i] = insert(root[i - 1], 0, N, a[i]);

    while (m--) {
        int l, r, k;
        l = read(); r = read(); k = read();
        printf("%d\n", query(root[r], root[l - 1], 0, N, k));
    }
    // system("pause");
    return 0;
}

 

posted @ 2020-07-24 02:07  violet72  阅读(212)  评论(0编辑  收藏  举报