标签:暴力 alt 插入 ios using 其它 不能 get google
首先跟你说说这名字的由来。据说,是一位叫fotile主席的大大在写一道题时因为不会划分树就临时yy出一个算法,于是,这算法就这么诞生了。(这就是大佬吗Orz…)
主席树全称叫可持续化线段树,好复杂。其实就是可以重复利用信息的线段树,从而减小空间和时间的开销。举个例子,为了做到重复利用信息,它时这个样子的:
去孤独·粲泽博客找的的图片,ta讲的也特别好辣,推荐大家去看看
看到没,上面那就是一棵标准的主席树,是不是跟线段树不太一样,它很多点是共用的
那么主席树这种数据结构就可以解决这类问题辣,怎么解决,继续往下看叭QwQ
上面那句话很rao口,下面我们来模拟一组数据
现有数列:1 5 2 6 3 7 4,离散化后为1 5 2 6 3 7 4,依次插入
图片摘自bestFy的博客,这位大大的图更助我理解了主席树,感谢!
首先空树建好qwq
我们还没做到重复利用信息啊!怎么做到,继续看叭QwQ
你会发现,每次只有根节点到一个叶子结点的一条链上的点val值发生了变化,其它点都不变。所以我们就利用这点,改变的地方就更新,不变的地方就用上一个主席树的信息就好!
下面针对上面那个样例,直接给出真正建树的逐过程图片!(自己画的QwQ)
留坑待填
如果你认为自己懂了上面我所讲的,那么主席树的算法思路你听懂了(这也是最难的地方)
还有至于代码,我喜欢用结构体,开数组也行的,差不多。还有代码中有一些细节的地方我在正文中并没有提到,不懂的同学先自己想想,实在想不通了就去问问身边的学长或去Google下(我也是这样走过来的)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#define maxn 100005 * 2
using namespace std;
set<int> st;
map<int, int> mp1, mp2;
struct Tree {int sum, l, r;} tree[maxn << 5];
int n, m, g, index;
int a[maxn], b[maxn], rt[maxn];
int read()
{
int x = 0, f = 1; char c = getchar();
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;
}
int build(int l, int r)
{
int t = ++index, mid = (l+r) >> 1;
if (l < r)
{
tree[t].l = build(l, mid);
tree[t].r = build(mid+1, r);
}
return t;
}
int update(int last, int l, int r, int x)
{
int t = ++index, mid = (l+r) >> 1;
tree[t].l = tree[last].l; tree[t].r = tree[last].r; tree[t].sum = tree[last].sum + 1;
if (l < r)
{
if (x <= mid) tree[t].l = update(tree[last].l, l, mid, x);
else tree[t].r = update(tree[last].r, mid+1, r, x);
}
return t;
}
int ask(int u, int v, int l, int r, int k)
{
if (l >= r) return l;
int x = tree[tree[v].l].sum - tree[tree[u].l].sum, mid = (l + r) >> 1;
if (x >= k) return ask(tree[u].l, tree[v].l, l, mid, k);
else return ask(tree[u].r, tree[v].r, mid+1, r, k-x);
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++) a[i] = read(), st.insert(a[i]);
while(!st.empty()) {mp1[*st.begin()] = ++g, mp2[g] = *st.begin(); st.erase(st.begin());}
for (int i = 1; i <= n; i ++) rt[i] = update(rt[i-1], 1, g, mp1[a[i]]);
rt[0] = build(1, g);
for(int i = 1; i <= m; i++)
{
int l = read(), r = read(), k = read();
printf("%d\n", mp2[ask(rt[l - 1], rt[r], 1, g, k)]);
}
return 0;
}
标签:暴力 alt 插入 ios using 其它 不能 get google
原文地址:https://www.cnblogs.com/BigYellowDog/p/10326652.html