洛谷P1972 [SDOI2009]HH的项链(BZOJ1878)

莫队

洛谷题目传送门
BZOJ题目传送门

莫队大法好!(本来还想着写个树状数组什么的)

注意不要算重喽!

代码:

#include
#include
#include
#include
#include
#define N 50000
#define MX 1000000
#define MM 200000
using namespace std;
struct qstn{
    int l,r,id,kl,kr;
    bool operator <(const qstn &t) const{
        return (t.kl>kl||(t.kl==kl&&t.kr>kr));
    }
}que[MM+5];
int n,m,sum;
int ans[MM+5],t[MX+5],a[N+5];
inline char readc(){
    static char buf[100000],*l=buf,*r=buf;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    if (l==r) return EOF; return *l++;
} 
inline int _read(){
    int num=0; char ch=readc();
    while (!isdigit(ch)) ch=readc();
    while (isdigit(ch)) { num=num*10+ch-48; ch=readc(); }
    return num;
}
void nsrt(int l,int r,int flag){
    for (int i=l;i<=r;i++){
        if (!t[a[i]]&&flag==1) sum++;
        if (t[a[i]]==1&&flag==-1) sum--;
        t[a[i]]+=flag;
    }
}
int main(){
    n=_read(); int kk=sqrt(n);
    for (int i=1;i<=n;i++) a[i]=_read();
    m=_read();
    for (int i=1;i<=m;i++){
        que[i].l=_read(),que[i].r=_read(),que[i].id=i;
        que[i].kl=(que[i].l-1)/kk+1,que[i].kr=(que[i].r-1)/kk+1;
    }
    sort(que+1,que+m+1);
    int l=que[1].l,r=que[1].r,nd=que[1].id;
    nsrt(l,r,1); ans[nd]=sum;
    for (int i=2;i<=m;i++){
        if (que[i].l>l) nsrt(l,que[i].l-1,-1);
        else nsrt(que[i].l,l-1,1);
        if (que[i].r>r) nsrt(r+1,que[i].r,1);
        else nsrt(que[i].r+1,r,-1);
        l=que[i].l,r=que[i].r;
        nd=que[i].id; ans[nd]=sum;
    }
    for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

你可能感兴趣的:(BZOJ,洛谷,其他---莫队,蒟蒻zxl的Blog专栏)