求任意一个区间中只出现一次的数
区间问题用主席树维护,对前缀建主席树。
主席树需要维护该元素上一次出现的位置,
如果[l,r]中元素上一次出现的位置小于l,则说明有解(并且解就是这个元素)
所以主席树需要维护区间最小值,顺带维护最小值出现的下标。
如果一个元素在区间中出现了很多次:
eg:5,6,5,7,5,8
则元素5上一次出现的位置会不断被后面新出现的5更新。故答案是正确的。
每个版本相较于上一个版本:1.将此位置的值更改为last[i]
2.如果这个数之前出现过,则将last[i]这个位置重新置为INF
#include <bits/stdc++.h>
using namespace std;
//-----pre_def----
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define fir(i, a, b) for (int i = (a); i <= (b); i++)
#define rif(i, a, b) for (int i = (a); i >= (b); i--)
#define endl '\n'
#define init_h memset(h, -1, sizeof h), idx = 0;
#define lowbit(x) x &(-x)
//---------------
const int N = 5e5 + 10;
int n, m, d[N];
int root[N], ls[N * 50], rs[N * 50], minx[N * 50]/*最小值*/, minsub[N * 50]/*最小值出现的下标*/, idx;
int last[N];
//每个节点维护最小值&最小值出现的位置
void pushup(int u)
{
if (minx[ls[u]] > minx[rs[u]])
{
minx[u] = minx[rs[u]];
minsub[u] = minsub[rs[u]];
}
else
{
minx[u] = minx[ls[u]];
minsub[u] = minsub[ls[u]];
}
}
void build(int &u, int l, int r) //初始化
{
u = ++idx;
if (l == r)
{
minx[u] = INF;
minsub[u] = l;
return;
}
int mid = l + r >> 1;
build(ls[u], l, mid);
build(rs[u], mid + 1, r);
pushup(u);
}
void update(int &now, int pre, int l, int r, int x, int k)
{
now = ++idx;
ls[now] = ls[pre];
rs[now] = rs[pre];
// minx[now] = minx[pre];
// minsub[now] = minsub[pre];
if (l == r)
{
minx[now] = k;
minsub[now] = l;
return;
}
int mid = l + r >> 1;
if (x <= mid)
{
update(ls[now], ls[pre], l, mid, x, k);
}
else
{
update(rs[now], rs[pre], mid + 1, r, x, k);
}
pushup(now);
}
PII query(int now, int l, int r, int L, int R)
{
if (L <= l && r <= R)
{
return {minx[now], minsub[now]};
}
int mid = l + r >> 1;
if (R <= mid) //只需要ls就行了
{
return query(ls[now], l, mid, L, R);
}
else if (mid < L) //只需要rs就行了
{
return query(rs[now], mid + 1, r, L, R);
}
else
{
//返回区间最小值&出现的下标
PII ll = query(ls[now], l, mid, L, R), rr = query(rs[now], mid + 1, r, L, R);
if (ll.first <= rr.first)
return ll;
else
return rr;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
int StartTime = clock();
#endif
scanf("%d", &n);
build(root[0], 1, n);
fir(i, 1, n)
{
scanf("%d", &d[i]);
//新建版本,修改1~2处
update(root[i], root[i - 1], 1, n, i, last[d[i]]);
if (last[d[i]]) //之前出现过
{
update(root[i], root[i], 1, n, last[d[i]], INF);
}
last[d[i]] = i;
}
scanf("%d", &m);
while (m--)
{
int l, r;
scanf("%d%d", &l, &r);
PII ans = query(root[r], 1, n, l, r);
//cout << ans.first << " " << ans.second << endl;
if (ans.first >= l)
{
puts("0");
}
else
{
printf("%d\n", d[ans.second]);
}
}
#ifndef ONLINE_JUDGE
printf("Run_Time = %d ms\n", clock() - StartTime);
#endif
return 0;
}