【模板】BZOJ 3781: 小B的询问 莫队算法

http://www.lydsy.com/JudgeOnline/problem.php?id=3781

N个数的序列,每次询问区间中每种数字出现次数的平方和,可以离线。

丢模板:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=50005, S=225;
int be[MAXN], A[MAXN], c[MAXN], ans[MAXN], N, M, K;
struct Qry{
    int l, r, id;
    bool operator<(const Qry &o)const{
        if(be[l]==be[o.l]) return (be[l]&1)?r>o.r:r<o.r;
        return be[l]<be[o.l];
    }
}Q[MAXN];
int main(){
    scanf("%d%d%d", &N, &M, &K);
    for(int i=1; i<=N; ++i) be[i]=i/S;
    for(int i=1; i<=N; ++i) scanf("%d", A+i);
    for(int i=0; i<M; ++i) scanf("%d%d", &Q[i].l, &Q[i].r), Q[i].id=i;
    sort(Q, Q+M);
    for(int i=0, l=1, r=0, s=0; i<M; ++i){
        while(r<Q[i].r){int x=A[++r]; s+=2*(c[x]++)+1;}
        while(l>Q[i].l){int x=A[--l]; s+=2*(c[x]++)+1;}
        while(r>Q[i].r){int x=A[r--]; s+=-2*(c[x]--)+1;}
        while(l<Q[i].l){int x=A[l++]; s+=-2*(c[x]--)+1;}
        ans[Q[i].id]=s;
    }
    for(int i=0; i<M; ++i) printf("%d\n", ans[i]);
    return 0;
}
posted @ 2017-03-21 16:32  will7101  阅读(191)  评论(0编辑  收藏  举报