牛客暑期ACM多校第一场 J Different Integers 离线树状数组,区间不同数

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;
}

猜你喜欢

转载自blog.csdn.net/m0_38013346/article/details/81179902