P1972 [SDOI2009]HH的项链

简化题目:
静态维护,离线询问区间种类数
考虑运用树状数组,对每组询问r从小到大排序,依次不断更新前缀
如果该种颜色已经出现过,就在上一次出现的位置-1
然后对该位置+1,将该颜色上次出现的位置更新为该位置

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 1000119
int num[maxn],tree[maxn],booll[maxn],nnn[maxn],N,ww;;
//num数组保存原数列,tree树状数组,nnn保存结果
struct tt
{
    int l,r;
    int pos;
};
tt ask[maxn];
bool cmp(tt x,tt y)
{ 
    return x.r<y.r;
}
int lowbit(int n) 
{
    return n&(-n);
}
void add(int n,int now)
{
    while(n<=N)
    {
        tree[n]+=now;
        n+=lowbit(n);
    }
}
int sum(int n)
{
    int ans=0;
    while(n!=0)
    {
        ans+=tree[n];
        n-=lowbit(n);
    }
    return ans;
}
int main()
{
        scanf("%d",&N);
        for(int i=1;i<=N;i++)
            scanf("%d",&num[i]);
        scanf("%d",&ww);
        for(int i=1;i<=ww;i++)
        {
            scanf("%d%d",&ask[i].l,&ask[i].r);
            ask[i].pos=i; 
        }
        sort(ask+1,ask+1+ww,cmp);
        int next=1;
        for(int i=1;i<=ww;i++)
        {
            for(int j=next;j<=ask[i].r;j++)
            {
                if(booll[num[j]]) 
                    add(booll[num[j]],-1);
                add(j,1);
                booll[num[j]]=j;
            }
            next=ask[i].r+1;
            nnn[ask[i].pos]=sum(ask[i].r)-sum(ask[i].l-1);
        }
    for(int i=1;i<=ww;i++)
      cout<<nnn[i]<<endl;
    return  0;
}
posted @   wzx_believer  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示