题中问的是从1到i 和 j到n 虽然是取了两边 但也是区间处理问题
莫队可以做。。不过时间是个玄学
正解做法是树状数组,先倍增区间 然后将所有的询问存下来按照右区间递增排序
用map记录 第一次出现和最后一次出现
#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int N = 3e5 + 10;
const int inf = 0x3f3f3f3f;
int a[N], n, m, ans[N], c[N];
map<int, int> mp;
int lowbit(int x)
{
return x & -x;
}
void add(int i, int k)
{
while (i <= n)
{
c[i] += k;
i += lowbit(i);
}
}
int sum(int i)
{
int res = 0;
while (i > 0)
{
res += c[i];
i -= lowbit(i);
}
return res;
}
struct node
{
int l, r, id;
} query[N];
bool cmp(node x, node y)
{
return x.r < y.r;
}
int main()
{
while (~scanf("%d%d", &n, &m))
{
mem(c, 0);
mp.clear();
//输入 , 倍增
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
a[i + n] = a[i];
}
for (int i = 0; i < m; i++)
{
scanf("%d%d", &query[i].r, &query[i].l);
query[i].r += n;
query[i].id = i;
}
n <<= 1;
sort(query, query + m, cmp);
int cur = 1;
for (int i = 0; i < m; i++)
{
for (int j = cur; j <= query[i].r; j++)
{
if (mp.find(a[j]) != mp.end())
{
add(mp[a[j]], -1);
}
add(j, 1);
mp[a[j]] = j;
}
cur = query[i].r + 1;
ans[query[i].id] = sum(query[i].r) - sum(query[i].l - 1);
}
for (int i = 0; i < m; i++)
printf("%d\n", ans[i]);
}
return 0;
}