您的位置:首页 > 其它

BZOJ-3809 Gty的二逼妹子序列 莫队算法 分块

2017-07-04 20:20 381 查看

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

3809: Gty的二逼妹子序列

Time Limit: 80 Sec Memory Limit: 28 MB

Submit: 1919 Solved: 572

[Submit][Status][Discuss]

Description

Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题。

对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数。

为了方便,我们规定妹子们的美丽度全都在[1,n]中。

给定一个长度为n(1<=n<=100000)的正整数序列s(1<=si<=n),对于m(1<=m<=1000000)次询问“l,r,a,b”,每次输出sl…sr中,权值∈[a,b]的权值的种类数。

Input

第一行包括两个整数n,m(1<=n<=100000,1<=m<=1000000),表示数列s中的元素数和询问数。

第二行包括n个整数s1…sn(1<=si<=n)。

接下来m行,每行包括4个整数l,r,a,b(1<=l<=r<=n,1<=a<=b<=n),意义见题目描述。

保证涉及的所有数在C++的int内。

保证输入合法。

Output

对每个询问,单独输出一行,表示sl…sr中权值∈[a,b]的权值的种类数。

Sample Input

10 10

4 4 5 1 4 1 5 1 2 1

5 9 1 2

3 4 7 9

4 4 2 5

2 3 4 7

5 10 4 4

3 9 1 1

1 4 5 9

8 9 3 3

2 2 1 6

8 9 1 4

Sample Output

2

0

0

2

1

1

1

0

1

2

HINT

样例的部分解释:

5 9 1 2

子序列为4 1 5 1 2

在[1,2]里的权值有1,1,2,有2种,因此答案为2。

3 4 7 9

子序列为5 1

在[7,9]里的权值有5,有1种,因此答案为1。

4 4 2 5

子序列为1

没有权值在[2,5]中的,因此答案为0。

2 3 4 7

子序列为4 5

权值在[4,7]中的有4,5,因此答案为2。

建议使用输入/输出优化。

Source

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

namespace FastIO  {
const size_t str = 1 << 20;

struct Reader  {
char buf[str], *s, *t, ch;
Reader ( ) : s( ), t( ), buf ( ) {    }
inline char pick ( )  {
return (s == t) ? ( t = buf + fread ( s = buf, 1, str , stdin ), *s++ ) : ( *s++ );
}

template < class T >
inline Reader& operator >> ( T& x )  {
while ( !isdigit ( ch = pick ( ) ) );
for ( x = -48 + ch; isdigit ( ch = pick () ); ( x *= 10 ) += ch - 48 ) ;
return *this;
}

} cin;

struct Writer  {
char buf[str], *s, *t;
Writer () : s ( buf ), t( buf + str ), buf ( ) {    }
~Writer () { fwrite( buf, 1, s - buf, stdout ); }

inline void echo ( char c )  {
( s == t ) ? ( fwrite ( s = buf, 1, str, stdout ), *s++ = c ) : ( *s++ = c );
}

inline Writer& operator << ( long long x )  {
if( !x ) return echo( 48 ), *this;
static int t[21], top;
while ( x ) t[++top] = x % 10, x /= 10;
while ( top ) echo(t[top--] + 48);
return *this;
}
inline Writer& operator << (const char* s)  {
while ( *s ) echo( *s++ ) ;
return *this;
}
} cout;
const char *endl = "\n";
}

using namespace FastIO ;

const int N  = 100005 ;

int sq, pos
;
int pos_cnt [505] ;

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

int n, m, k ;
int a
;
int c
;
int answer [N * 10] ;

inline void Update ( int x, int delta )  {
c [a [x]] += delta ;
if ( delta ^ -1 )  {
if ( c [a [x]] == 1 )  ++ pos_cnt [pos [a [x]]] ;  // devide the value of w ;
return ;
}
if ( !c [a [x]] )  -- pos_cnt [pos [a [x]]] ;
}

inline int Query ( int a, int b )  {
int rt = 0 ;
if ( pos [b] <= pos [a] + 1 )  {
for ( int i = a ; i <= b ; ++ i )
if ( c [i] )  ++ rt ;
return rt ;
}
for ( int i = pos [a] + 1 ; i < pos [b] ; ++ i )  // solve ( pos [x], pos [y] ) ;
rt += pos_cnt [i] ;
for ( int i = a ; i <= pos [a] * sq ; ++ i )  // solve block x inside ;
if ( c [i] )  ++ rt ;
for ( int i = ( pos [b] - 1 ) * sq + 1 ; i <= b ; ++ i )  // solve block y inside ;
if ( c [i] )  ++ rt ;
return rt ;
}

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] = Query ( q [i].a, q [i].b ) ;
}
}

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