BZOJ3781[小B的询问]

来源:互联网 发布:泰安网络推广 编辑:程序博客网 时间:2024/05/16 05:08

Description

小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。


Input

第一行,三个整数N、M、K。
第二行,N个整数,表示小B的序列。
接下来的M行,每行两个整数L、R。


Output

M行,每行一个整数,其中第i行的整数表示第i个询问的答案。
Sample Input
6 4 3
1 3 2 1 1 3
1 4
2 6
3 5
5 6


Sample Output

6
9
5
2


solution: 莫队裸题

以sort(n)为大小分块

以 l所在块为第一关键字,r为二关键字排序


/**************************************************************    Problem: 3781    User: Venishel    Language: C++    Result: Accepted    Time:1632 ms    Memory:3064 kb****************************************************************/#include <cmath>#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;#define N 50005#define LL long longint a[N];int n, m, k;LL cnt[N], res[N];struct E{    int l, r, bk, id;}b[N];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;}bool operator<( E a, E b){    if ( a.bk == b.bk ) return a.r < b.r;    return a.bk < b.bk;}void solve(){    sort( b+1, b+1+m);    int l = 1, r = 0;    LL ans = 0;    for ( int i = 1; i <= m; i++){        for ( ; l > b[i].l ;  ) l--, cnt[ a[l] ]++, ans += 2*cnt[a[l]] - 1;        for ( ; l < b[i].l ; l++ ) cnt[ a[l] ]--, ans -= 2*cnt[a[l]] + 1;        for ( ; r > b[i].r ; r-- ) cnt[ a[r] ]--, ans -= 2*cnt[a[r]] + 1;        for ( ; r < b[i].r ;  ) r++, cnt[ a[r] ]++, ans += 2*cnt[a[r]] - 1;        res[ b[i].id ] = ans;    }}int main(){    n = read(), m = read(), k = read();    //scanf( "%d%d%d", &n, &m, &k );    for ( int i = 1; i <= n; i++ ) a[i] = read();    int blk = sqrt( n );    for ( int i = 1; i <= m; i++){        b[i].l = read(), b[i].r = read();        //scanf( "%d%d", &b[i].l, &b[i].r );        b[i].id = i;        b[i].bk = ( b[i].l-1 ) / blk + 1;    }    solve();    for ( int i = 1; i <= m; i++ )        printf( "%lld\n", res[i] );}
原创粉丝点击