基礎莫隊模板

9102700發表於2024-06-22

這是一篇不帶修改的莫隊
原來莫隊是利用分塊的思想最佳化一個路徑(曼哈頓距離)-- 幾何解釋

int n, m, a[N];

struct Q{
    int l, r, id;
}q[N];
int pos[N], cnt[N], ans[N];
ll ANS;

bool mo_cmp(Q x, Q y){
    if(pos[x.l] != pos[y.l]){
        return pos[x.l] < pos[y.l];
    }
    if(pos[x.l] & 1) return x.r > y.r;  // 奇偶性最佳化
    else return x.r < y.r;
}

void add(int x){
    ANS -= cnt[a[x]]*cnt[a[x]];
    cnt[a[x]]++;
    ANS += cnt[a[x]]*cnt[a[x]];
}
void del(int x){
    ANS -= cnt[a[x]]*cnt[a[x]];
    cnt[a[x]]--;
    ANS += cnt[a[x]]*cnt[a[x]];
}

inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}

void write(int x)
{
    if(x<0)
        putchar('-'),x=-x;
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
    return;
}

void solve() {
    int k;
    n = read(); m = read(); k = read();
    int block = sqrt(n);
    for(int i = 1; i <= n; i++){
        a[i] = read();
        pos[i] = (i - 1)/block + 1;
    }
    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, mo_cmp);
    int L = 1, R = 0;
    for(int i = 1; i <= m; i++){
        while(L < q[i].l) del(L), L++;
        while(L > q[i].l) L--, add(L);
        while(R < q[i].r) R++, add(R);
        while(R > q[i].r) del(R), R--;
        ans[q[i].id] = ANS;
    }
    for(int i = 1; i <= m; i++) write(ans[i]), putchar('\n');
}

相關文章