您的位置:首页 > 其它

BZOJ - 3781 小B的询问 莫队算法

2017-07-04 17:14 363 查看

大家都很强, 可与之共勉 。

3781: 小B的询问

Time Limit: 10 Sec Memory Limit: 128 MB

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

HINT

对于全部的数据,1<=N、M、K<=50000

Source

垃圾裸莫队算法

# include <cmath>
# include <cstdio>
# include <algorithm>

const int N  = 50005 ;

int sq, pos
;

struct Query  {
int l, r, id ;
inline short operator < ( const Query& rhs )  const  {
return ( pos [l] < pos[rhs.l] ) || ( pos [l] == pos[rhs.l] && r < rhs.r ) ;
}
} q
;

int n, m, k ;
int a
;
int c
;
int ans ;
int answer
;

inline void Update ( int pos, int delta )  {
ans += delta * ( c [a [pos]] << 1 ) + 1 ;
c [a [pos]] += delta ;
}

void Solve ( )  {
for( register int i = 1, l = 1, r = 0; i <= m ; ++ i )  {
while ( r < q [i].r )
Update ( ++ r, 1 ) ;
while ( r > q [i].r )
Update ( r --, -1 ) ;
while ( l < q [i].l )
Update ( l ++, -1 ) ;
while ( l > q [i].l )
Update ( -- l, 1 ) ;
answer [q [i].id] = ans ;
}
}

int main ( )  {
scanf ( "%d%d%d", & n, & m, & k ) ;
for ( int i = 1 ; i <= n ; ++ i )   scanf ( "%d", a + i ) ;
sq = sqrt ( n ) ;
for ( int i = 1 ; i <= n ; ++ i )   pos [i] = ( i - 1 ) / sq + 1 ;
for ( int i = 1 ; i <= m ; ++ i )  {
scanf ( "%d%d", &q [i].l, &q [i].r ) ;
q [i].id = i ;
}
std :: sort ( q + 1, q + 1 + m ) ;
Solve ( ) ;
for ( int i = 1 ; i <= m ; ++ i )  printf ( "%d\n", answer [i] ) ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: