1. 程式人生 > >bzoj 1878: [SDOI2009]HH的項鏈【樹狀數組】

bzoj 1878: [SDOI2009]HH的項鏈【樹狀數組】

當前 ostream return spa \n sort 排序 升序 一個

對於一個lr,每個顏色貢獻的是在(1,r)區間裏出現的最右位置,所以記錄一個b數組表示當前點這個顏色上一個出現的位置
然後把詢問離線,按r升序排序
每次把右端點右移,把這個點在樹狀數組上+1,並且在當前這個點的b位置上-1(表示沒用了),然後樹狀數組前綴和減一下即可
我寫的莫隊會T

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1000005;
int n,m,a[N],b[N],la[N],t[N],ans[N];
struct qwe
{
    int l,r,id;
}q[N];
bool cmp(const qwe &a,const qwe &b)
{
    return a.r<b.r;
}
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>‘9‘||p<‘0‘)
    {
        if(p==‘-‘)
            f=-1;
        p=getchar();
    }
    while(p>=‘0‘&&p<=‘9‘)
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
void update(int x,int w)
{
    if(x==0)
        return;
    for(int i=x;i<=n;i+=(i&(-i)))
        t[i]+=w;
}
int ques(int x)
{
    int r=0;
    for(int i=x;i>=1;i-=(i&(-i)))
        r+=t[i];
    return r;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read(),b[i]=la[a[i]],la[a[i]]=i;
    m=read();
    for(int i=1;i<=m;i++)
        q[i].l=read(),q[i].r=read(),q[i].id=i;
    sort(q+1,q+1+m,cmp);
    int r=0;
    for(int i=1;i<=m;i++)
    {
        while(r<q[i].r)
            r++,update(b[r],-1),update(r,1);
        ans[q[i].id]=ques(q[i].r)-ques(q[i].l-1);
    }
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    return 0;
}

bzoj 1878: [SDOI2009]HH的項鏈【樹狀數組】