Link
J Different Integers
题意
给出n个元素的数组,和q次查询,每次查询输入l,r。查询[1,l]和[r,n]两个区间的不同数的个数。
题解
1) 由于我们知道求单个闭区间的不同数个数是很好求的参考SPOJ - DQUERY D-query
那么我们只需要将n的元素的数组往后复制一份,那么就变成了上面的题目了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int arr[maxn],ans[maxn],vis[maxn];
int n,q;
struct BIT
{
int c[maxn];
void init() {
memset(c,0,sizeof(c));
}
int lowbit(int x) { return x & -x;}
void update(int pos,int val) {
if(pos == 0) return;
for(int i=pos;i<maxn;i+=lowbit(i)) c[i] += val;
}
int query(int pos) {
int ans = 0;
for(int i=pos;i>0;i-=lowbit(i)) ans += c[i];
return ans;
}
}bit;
struct node {
int ql,qr,id;
bool operator < (const node &a) const {
return qr < a.qr;
}
};
node Qu[maxn];
int main()
{
while(~scanf("%d%d",&n,&q))
{
bit.init();
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) {
scanf("%d",&arr[i]);
arr[i+n]=arr[i];
}
for(int i=1;i<=q;i++) {
scanf("%d%d",&Qu[i].qr,&Qu[i].ql);
Qu[i].id = i;
Qu[i].qr += n;
}
sort(Qu+1,Qu+1+q);
int cur = 1;
// printf("Yes\n");
for(int i=1;i<=2*n;i++) {
if(!vis[arr[i]]) {
vis[arr[i]] = i;
bit.update(i,1);
}
else {
bit.update(vis[arr[i]],-1);
vis[arr[i]] = i;
bit.update(i,1);
}
while(cur <= q && Qu[cur].qr == i) {
ans[Qu[cur].id] = bit.query(Qu[cur].qr) - bit.query(Qu[cur].ql-1);
cur++;
}
}
for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
}
return 0;
}
2) 同样我们也可以反向来思考这个问题,首先我们先计算出整个数组的不同元素个数。
然后对于每一个查询我们减去在(l,r)中完全出现的元素,完全出现表示只在(l,r)中出现。
减去就是答案。
用树状数组维护一下每个位置的答案的贡献。
具体见代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
struct BIT
{
int c[maxn];
void init() {
memset(c,0,sizeof(c));
}
int lowbit(int x) {return x & -x;}
void update(int pos,int val) {
if(!pos) return;
for(int i=pos;i<maxn;i+=lowbit(i)) c[i]+=val;
}
int query(int pos) {
int ans = 0;
for(int i=pos;i>0;i-=lowbit(i)) ans+=c[i];
return ans;
}
}bit;
struct node
{
int ql,qr,id;
bool operator < (const node &a)const {
return qr < a.qr;
}
};
node qu[maxn];
int arr[maxn],fir[maxn],las[maxn],ans[maxn],n,q,tot;
inline void init() {
bit.init();
memset(fir,0,sizeof(fir));
memset(las,0,sizeof(las));
tot = 0;
}
int main()
{
while(~scanf("%d%d",&n,&q))
{
init();
for(int i=1;i<=n;i++) {
scanf("%d",&arr[i]);
if(!fir[arr[i]]) tot++,fir[arr[i]]=i;
las[arr[i]] = i;
}
for(int i=1;i<=q;i++) {
scanf("%d%d",&qu[i].ql,&qu[i].qr);
qu[i].id = i;
}
sort(qu+1,qu+1+q);
for(int i=1,cur=1;i<=n;i++) {
while(cur <= q && qu[cur].qr == i) {
ans[qu[cur].id] = tot;
ans[qu[cur].id] -= (bit.query(qu[cur].qr) - bit.query(qu[cur].ql-1));
cur++;
}
if(las[arr[i]] == i) {
bit.update(fir[arr[i]]-1,1);
}
}
for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
}
return 0;
}