和蒲公英差不多的套路,预处理整块的答案,查询的时候分类讨论,如果一个数在整段中是偶数次,在中间的整块是奇数次那么,在整段是奇数次在中间的整块是偶数次就。效率是。必须O2+优秀的块的大小才可以卡过去。注意不要用memset,每次处理过后for一遍清空就好,memset是对整个数组清空.

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f 
#define il inline 

namespace io {

    #define debug_ puts("debuging ... ") ;
    #define in(a) a=read()
    #define out(a) write(a)
    #define outn(a) out(a),putchar('\n')

    #define I_int int 
    inline I_int read() {
        I_int x = 0 , f = 1 ; char c = getchar() ;
        while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; } 
        while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; } 
        return x * f ;
    } 
    char F[ 200 ] ;
    inline void write( I_int x ) {
        I_int tmp = x > 0 ? x : -x ;
        if( x == 0 ) putchar( '0' ) ;
        if( x < 0 ) putchar( '-' ) ;
        int cnt = 0 ;
        while( tmp > 0 ) {
            F[ cnt ++ ] = tmp % 10 + '0' ;
            tmp /= 10 ;
        }
        while( cnt > 0 ) putchar( F[ -- cnt ] ) ;
    }
    #undef I_int

}
using namespace io ;

using namespace std ;

#define N 100010

vector < int > vt[ N ] ;
int n = read() , c = read() , m = read() ;
int L[ N ] , R[ N ] , bl[ N ] , cnt[ 1510 ][ 1510 ] ;
int block , num , tot[ N ] , a[ N ] ;

void pre( int x ) {
    int ans = 0 ;
    for( int i = L[ x ] ; i <= n ; i ++ ) {
        int t = bl[ i ] ;        
        tot[ a[ i ] ] ++ ;
        if( tot[ a[ i ] ] % 2 == 0 && tot[ a[ i ] ] ) ans ++ ;
        if( tot[ a[ i ] ] % 2 && tot[ a[ i ] ] > 1 ) ans -- ; 
        cnt[ x ][ t ] = ans ;
    }
    for( int i = L[ x ] ; i <= n ; i ++ ) tot[ a[ i ] ] = 0 ;
}

void build() { 
    block = sqrt((double)n/log((double)n)*log(2)) ; 
    num = n / block ; 
    if( n % block ) num ++ ;
    for( int i = 1 ; i <= num ; i ++ ) {
        L[ i ] = (i - 1) * block + 1 ;
        R[ i ] = i * block ;
    } 
    for( int i = 1 ; i <= n ; i ++ ) 
        bl[ i ] = (i - 1) / block + 1 ;
    for( int i = 1 ; i <= num ; i ++ ) pre( i ) ; 
}

int serach_ans( int l , int r , int x ) {
    int t = upper_bound( vt[ x ].begin() , vt[ x ].end() , r ) - lower_bound( vt[ x ].begin() , vt[ x ].end() , l ) ;
    return t ; 
}

int query( int x , int y ) {
    int ans = 0 ;
    if( bl[ x ] == bl[ y ] ) {
        for( int i = x ; i <= y ; i ++ ) {
            if( tot[ a[ i ] ] ) continue ;
            tot[ a[ i ] ] = 1 ;
            int t = serach_ans( x , y , a[ i ] ) ;
            if( t % 2 == 0 && t ) ans ++ ; 
        }
        for( int i = x ; i <= y ; i ++ ) tot[ a[ i ] ] = 0 ;
        return ans ;
    }
    int l = L[ bl[ x ] + 1 ] , r = R[ bl[ y ] - 1 ] ; 
    ans = cnt[ bl[ x ] + 1 ][ bl[ y ] - 1 ] ;
    for( int i = x ; i <= R[ bl[ x ] ] ; i ++ ) {
        if( tot[ a[ i ] ] ) continue ;
        tot[ a[ i ] ] = 1 ;
        int t2 = serach_ans( l , r , a[ i ] ) , t1 = serach_ans( x , y , a[ i ] ) ;
        if( t1 % 2 == 0 ) {
            if( t2 % 2 || !t2 ) ans ++ ;
        } else if( t2 % 2 == 0 && t2 ) ans -- ;
    }
    for( int i = L[ bl[ y ] ] ; i <= y ; i ++ ) {
        if( tot[ a[ i ] ] ) continue ;
        tot[ a[ i ] ] = 1 ;
        int t2 = serach_ans( l , r , a[ i ] ) , t1 = serach_ans( x , y , a[ i ] ) ;
        if( t1 % 2 == 0 ) {
            if( t2 % 2 || !t2 ) ans ++ ;
        } else if( t2 % 2 == 0 && t2 ) ans -- ;
    }
    for( int i = x ; i <= R[ bl[ x ] ] ; i ++ ) tot[ a[ i ] ] = 0 ;
    for( int i = L[ bl[ y ] ] ; i <= y ; i ++ ) tot[ a[ i ] ] = 0 ;
    return ans ;
} 

int main() {
    int ans = 0 ;
    for( int i = 1 ; i <= n ; i ++ ) {
        a[ i ] = read() ;
        vt[ a[ i ] ].push_back( i ) ;
    }
    build() ;
    for( int i = 1 ; i <= m ; i ++ ) {
        int l = read() , r = read() ;
        l = (l + ans) % n + 1 , r = (r + ans) % n + 1 ;
        if( l > r ) swap( l , r ) ;
        outn( ans = query( l , r ) ) ; 
    } 
    return 0 ; 
}