P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链

原题地址:

https://s1.ax1x.com/2020/10/26/BKZ1NF.png

这题看起来可以用莫队做,本来想水一下的,然而我逛了一圈题解发现数据被加强了。

我稍微想了一下主席树,感觉好像维护起来没什么用,可能是我太菜了。

Std:


个人的理解

其实这种想法就是在进行一种去重(消去重复的影响),让统计变成最简单的区间求和

既然我们区间颜色重叠会影响统计,那么我们只要记录当前最有效的颜色即可,区间右端点的排序保证了这种有效性。

Code:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 1000305
#define minn -105
#define ll long long int
#define ull unsigned long long int
#define uint unsigned int
inline int read()
{
    int ans=0;
    char last=' ',ch=getchar();
    while(ch<'0'|ch>'9')last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans;
    return ans;
}
struct Query
{
    int l,r,id;
    bool operator<(const Query& sec)const
    {
        return r<sec.r;
    }
}q[maxn];

int tree[maxn];
int a[maxn],ans[maxn],pos[maxn];
int n,m;
void renew(int x,int k)
{
    for(;x<=n;x+=(x&-x))tree[x]+=k;
}
int cal(int x)
{
    int t=0;
    for(;x;x-=(x&-x))t+=tree[x];
    return t;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
    }
    m=read();
    for(int i=0;i<m;i++)
    {
        q[i].l=read(),q[i].r=read();q[i].id=i;
    }
    sort(q,q+m);
    int cur=0;
    for(int i=0;i<m;i++)
    {
        while(cur<q[i].r)
        {
            cur++;
            if(pos[a[cur]]!=0)renew(pos[a[cur]],-1);
            renew(cur,1);
            pos[a[cur]]=cur;
        }
        ans[q[i].id]=cal(q[i].r)-cal(q[i].l-1);
    }

    for(int i=0;i<m;i++)
    {
        cout<<ans[i]<<"\n";
    }
    return 0;
}

posted @ 2020-10-26 20:51  et3_tsy  阅读(79)  评论(0编辑  收藏  举报