牛客网多校1 Different Integers(莫队或树状数组)

给你一个数组, 长度n<=1e5, q次询问(l, r), 输出区间[1, l], [r, n]中不同数字的个数, q<=1e5

莫队 简单粗暴:

#include 
 
using namespace std;
const int maxn=1e5+10;
struct node{
    int l,r,id;
}s[maxn];
int block[maxn],t,n,m;
int a[maxn],c[maxn],ans[maxn];
bool cmp(const node&a,const node &b)
{
    if(block[a.l]==block[b.l]) return a.rs[i].l)
            {
                c[a[l]]--;
                if(c[a[l]]==0)
                    num--;
                l--;
            }
            while(r>s[i].r)
            {
                r--;
                c[a[r]]++;
                if(c[a[r]]==1)
                    num++;
            }
            while(r

树状数组:

#include 

using namespace std;
const int maxn=1e5+10;
struct node{
    int l,r,id;
}s[maxn];
bool cmp(const node&a,const node&b)//右端点大的优先
{
    if(a.r==b.r) return a.lb.r;
}
int n,m,a[maxn],first[maxn],vis[maxn];
int sum[maxn];
int lowbit(int x){return x&-x;}
void update(int pos,int val)
{
    while(pos<=n)
    {
        sum[pos]+=val;
        pos+=lowbit(pos);
    }
}
int query(int pos)
{
    int ans=0;
    while(pos>0)
    {
        ans+=sum[pos];
        pos-=lowbit(pos);
    }
    return ans;
}
int pre[maxn],ans[maxn];
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(first,0,sizeof first);
        int res=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(!first[a[i]])
            {
                first[a[i]]=i;
                res++;
            }
            pre[i]=res;///记下i位置前面不同数的个数
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&s[i].l,&s[i].r);
            s[i].id=i;
        }
        sort(s+1,s+m+1,cmp);
        memset(sum,0,sizeof sum);
        memset(vis,0,sizeof vis);
        int l=0,r=n+1;
        res=0;///从后往前遇到的不同数的个数
        for(int i=1;i<=m;i++)
        {
            while(r>s[i].r)
            {
                r--;
                if(!vis[a[r]])
                {
                    res++;
                    vis[a[r]]=1;
                    update(first[a[r]],1);
                }
            }
            ans[s[i].id]=pre[s[i].l]+res-query(s[i].l);//s[i].l以前不同数的个数+res-前后重复出现的数量
        }
        for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    }

    return 0;
}

 

你可能感兴趣的:(莫队,树状数组,多校)