题目链接:https://www.nowcoder.com/acm/contest/139/J
题意:给一个长为N的数组,Q个询问,询问a_1 到 a_l, a_r 到 a_N有多少个不同的数字。
思路:模板题,clone原数组成为2*N长的数组,将分开的区间询问变为连续的区间询问然后就可以套板子了。主席树被卡,后来换了树状数组就可以了。
AC代码如下:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
using namespace std;
#define FSIO ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl;
const int MAXN = 200005;
const int MOD = 1e9+7;
const int INF = 1e9+7;
struct query
{
int l, r, id;
bool operator < (const query &a) const
{
return r < a.r;
}
}queries[MAXN];
int a[MAXN], vis[MAXN], tree[MAXN], ans[MAXN];
int N, Q;
int lowbit(int x) { return x&-x; }
void update(int pos, int val)
{
while(pos < MAXN)
{
tree[pos] += val;
pos += lowbit(pos);
}
}
int query(int pos)
{
int res = 0;
while(pos)
{
res += tree[pos];
pos -= lowbit(pos);
}
return res;
}
int main()
{
//freopen("output.txt","w+",stdout);
while(scanf("%d%d",&N,&Q)!=EOF)
{
memset(tree, 0, sizeof(tree));
memset(vis, 0, sizeof(vis));
for(int i=1;i<=N;++i)
{
scanf("%d",a+i);
a[i+N] = a[i];
}
int l, r;
for(int i=1;i<=Q;++i)
{
scanf("%d%d",&l,&r);
queries[i].l = r;
queries[i].r = l+N;
queries[i].id = i;
}
N*=2;
sort(queries+1,queries+1+Q);
for(int i=1,j=1;i<=Q&&j<=N;++j)
{
if(vis[a[j]]) update(vis[a[j]],-1);
update(j,1);
vis[a[j]] = j;
while(i<=Q&&queries[i].r<=j)
{
ans[queries[i].id] = query(queries[i].r) - query(queries[i].l-1);
i++;
}
}
for(int i=1;i<=Q;++i)
{
printf("%d\n",ans[i]);
}
}
return 0;
}