P1972 [SDOI2009]HH的项链


P1972 [SDOI2009]HH的项链

经典区间数颜色问题。

离线做法有树状数组和莫队,在线做法有主席树。

莫队做法十分暴力,直接维护每个数当前的 cnt 再在单点更新的时候更新答案即可。

树状数组做法:

对于每一个位置维护一个前缀位置 \(pre\),那么询问就相当于是询问区间多少个位置的 \(pre\)\(l\) 之前。

我们可以考虑离线下来然后差分,具体来说就是每次维护当前点为右端点,左端点为 1 时的值域树状数组,维护小于等于数 x 的 pre 有多少个,这个信息显然可以差分。

然后主席树做法就是在线维护,每次直接在多树上询问即可。

树状数组代码:

#include
#include
#include
#include
using namespace std;
struct node{
	int l,r;
	int before;
	int ans;
}q[1000005];
int a[1000005],n,m,c[1000005],pre[1000005],used[1000005],p[1000005];
inline int read(){int x=0,f=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
inline int lowbit(int x){return x&(-x);}
inline bool cmp(node o,node p){return o.r

莫队

#include
using namespace std;
#define ri register int
#define MAXN 1001000
#define MAXA 1001000
#define MAXQ 1001000
#include 
int a[MAXN],cnt[MAXA],bnum,q,n,belong[MAXA],siz,ans1[MAXQ];
struct node{
    int l,r,id;
}lin[MAXQ];

struct _io {
    char* s;
    _io() : s((char*)mmap(0, 1 << 25, PROT_READ, MAP_PRIVATE, fileno(stdin), 0)) {}
    operator int() {
        int x = 0,w=0;
        while((*s)<'0') w|=(!((*s)^45)),++s;
        while((*s)>='0') x=(x<<3)+(x<<1)+((*s++)&15);
        return x*(w?-1:1);
    }
} it;

#define read() it
template< typename T >inline void write(T x)
{
    if(x>9) write(x/10);
    putchar(x%10^48);
}
inline bool cmp(node a,node b)
{
    return (belong[a.l]^belong[b.l])?belong[a.l]b.r);
}

int main()
{
    n=read();
    siz=2135;
    bnum=ceil((double)n/siz);
    for(ri i=1;i<=n;++i)
    {
        belong[i]=i/siz;
    }
    for(ri i=1;i<=n;++i) a[i]=read();
    q=read();
    for(ri i=1;i<=q;++i)
    {
        lin[i].l=read(),lin[i].r=read();
        lin[i].id=i;
    }
    sort(lin+1,lin+1+q,cmp);
    int l=1,r=0,now=0;
    for(ri i=1;i<=q;++i)
    {
        int ql=lin[i].l,qr=lin[i].r;
        while(lql) now+=!cnt[a[--l]]++;
        while(rqr) now-=!--cnt[a[r--]];
        ans1[lin[i].id]=now;
    }
    for(ri i=1;i<=q;++i)
    {
        write(ans1[i]);
        putchar('\n');
    }
}