题目
有 n n n个礼物,每个礼物都有一个编号,有两种操作:
- 拿走位置 i i i的礼物
- 查询区间[l,r]有没有两个编号相同的礼物
题解
对于每个位置 i i i,维护两个信息:
l a s t [ i ] last[i] last[i]:表示上一个最近的 a i a_i ai的位置,如果没有置为 0 0 0
n e x t [ i ] next[i] next[i]:表示下一个最近的 a i a_i ai的位置,如果没有置为 n + 1 n+1 n+1
这样,就形成了一个链表式的结构。
- 拿走位置 i i i的物品,只需做类似于链表的删除操作即可。
- 查询区间[l,r]是否有两个物品,也就是查询区间内是否存在 l a s t [ i ] > = l last[i]>=l last[i]>=l。
代码
/*
* @Author: hesorchen
* @Date: 2020-07-19 17:00:02
* @LastEditTime: 2021-02-06 16:34:36
* @Description: 栽种绝处的花
*/
#include <bits/stdc++.h>
using namespace std;
int a[500010];
int last[500010];
int nxt[500010];
unordered_map<int, int> mp;
struct node
{
int k, l, r, maxx;
} tr[500010 << 2];
void pushup(int k)
{
tr[k].maxx = max(tr[k * 2].maxx, tr[k * 2 + 1].maxx);
}
void build(int k, int l, int r)
{
tr[k].l = l;
tr[k].r = r;
if (l == r)
{
tr[k].maxx = last[l];
return;
}
int mid = l + r >> 1;
build(k * 2, l, mid);
build(k * 2 + 1, mid + 1, r);
pushup(k);
}
void change(int k, int pos, int w)
{
if (tr[k].l == tr[k].r && tr[k].l == pos)
{
tr[k].maxx = w;
return;
}
int mid = tr[k].l + tr[k].r >> 1;
if (pos <= mid)
change(k * 2, pos, w);
else
change(k * 2 + 1, pos, w);
pushup(k);
}
int query(int k, int l, int r)
{
if (tr[k].l == l && tr[k].r == r)
return tr[k].maxx;
int mid = tr[k].l + tr[k].r >> 1;
if (r <= mid)
return query(k * 2, l, r);
else if (l > mid)
return query(k * 2 + 1, l, r);
else
return max(query(k * 2, l, mid), query(k * 2 + 1, mid + 1, r));
}
int main()
{
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
{
if (mp.count(a[i]))
{
last[i] = mp[a[i]];
mp[a[i]] = i;
}
else
{
last[i] = 0;
mp[a[i]] = i;
}
}
mp.clear();
for (int i = n; i >= 1; i--)
{
if (mp.count(a[i]))
{
nxt[i] = mp[a[i]];
mp[a[i]] = i;
}
else
{
nxt[i] = 0;
mp[a[i]] = i;
}
}
build(1, 1, n);
while (q--)
{
int opt;
scanf("%d", &opt);
if (opt == 1)
{
int temp;
scanf("%d", &temp);
int pos1 = last[temp];
int pos2 = nxt[temp];
nxt[pos1] = nxt[temp];
last[pos2] = last[temp];//类似于链表的删除操作
last[temp] = 0;
change(1, temp, last[temp]);
if (pos2 >= 1 && pos2 <= n)
change(1, pos2, last[pos2]);
}
else
{
int l, r;
scanf("%d %d", &l, &r);
if (query(1, l, r) >= l)
puts("1");
else
puts("0");
}
}
return 0;
}