zoukankan      html  css  js  c++  java
  • 【模板】主席树

    Update at 2019.10.9

    • 主席树的核心思想是多棵权值线段树对区间的划分具有一致性,且相同区间的值具有可减性。
    • 可持久化的思想体现在对任意区间 ([l,r]) 的处理上。

    代码如下

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 2e5 + 10;
    
    struct node {
    	int sz;
    	node *ls, *rs;
    	void pull() { // be careful
    		this->sz = 0;
    		if (ls) {
    			this->sz += ls->sz;
    		} 
    		if (rs) {
    			this->sz += rs->sz;
    		}
    	}
    } pool[maxn * 20];
    inline node *newnode() {
    	static int tot = 0;
    	return &pool[tot++];
    }
    
    node *insert(node *pre, int l, int r, int pos, int val) {
    	node *cur = newnode();
    	if (pre) { // be careful
    		*cur = *pre;
    	}
    	if (l == r) {
    		cur->sz += val;
    		return cur;
    	}
    	int mid = l + r >> 1;
    	if (pos <= mid) {
    		cur->ls = insert(pre ? pre->ls : NULL, l, mid, pos, val);
    	} else {
    		cur->rs = insert(pre ? pre->rs : NULL, mid + 1, r, pos, val);
    	}
    	cur->pull();
    	return cur;
    }
    int kth(node *cur, node *pre, int l, int r, int k) {
    	if (l == r) {
    		return l;
    	}
    	int mid = l + r >> 1;
    	int lsz = 0;
    	if (cur && cur->ls) lsz += cur->ls->sz; // be careful
    	if (pre && pre->ls) lsz -= pre->ls->sz;
    	if (k <= lsz) {
    		return kth(cur ? cur->ls : NULL, pre ? pre->ls : NULL, l, mid, k);
    	} else {
    		return kth(cur ? cur->rs : NULL, pre ? pre->rs : NULL, mid + 1, r, k - lsz);
    	}
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	int n, m;
    	cin >> n >> m;
    	vector<int> a(n + 1), d;
    	for (int i = 1; i <= n; i++) {
    		cin >> a[i];
    		d.push_back(a[i]);
    	}
    	sort(d.begin(), d.end());
    	d.erase(unique(d.begin(), d.end()), d.end());
    	for (int i = 1; i <= n; i++) {
    		a[i] = lower_bound(d.begin(), d.end(), a[i]) - d.begin() + 1;
    	}
    	int range = d.size();
    	vector<node*> rt(n + 1);
    	for (int i = 1; i <= n; i++) {
    		rt[i] = insert(rt[i - 1], 1, range, a[i], 1);
    	}
    	while (m--) {
    		int l, r, k;
    		cin >> l >> r >> k;
    		cout << d[kth(rt[r], rt[l - 1], 1, range, k) - 1] << endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    第七章习题G题
    第二周习题O题
    P4735 最大异或和
    P3008 [USACO11JAN]道路和飞机Roads and Planes
    P4009 汽车加油行驶问题
    P1073 最优贸易
    P2260 [清华集训2012]模积和
    P2865 [USACO06NOV]路障Roadblocks
    P1821 [USACO07FEB]银牛派对Silver Cow Party
    P4180 【模板】严格次小生成树[BJWC2010]
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10122069.html
Copyright © 2011-2022 走看看