QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#111442#3232. DaylightSorting100 ✓11681ms115824kbC++206.5kb2023-06-07 06:52:292023-06-07 06:52:33

Judging History

This is the latest submission verdict.

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-06-07 06:52:33]
  • Judged
  • Verdict: 100
  • Time: 11681ms
  • Memory: 115824kb
  • [2023-06-07 06:52:29]
  • Submitted

answer

#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef unsigned long long ull ;
typedef pair < int , int > pii ;
typedef vector < int > vi ;
#define fi first
#define se second
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()

const int MAXN = 2e5 + 7 ;
const int LOG = 19 ;

int n , q ;
vector < int > v[ MAXN ] ;
vector < int > ord ;
int st[ MAXN ] , en[ MAXN ] , lvl[ MAXN ] ;
int rmq[ LOG ][ 2 * MAXN ] ;
int pwid[ 2 * MAXN ] ;
int anc[ MAXN ][ LOG ] ;
int small_n ;

void dfs ( int x , int prv ) {
    ord.push_back ( x ) ;
    st[ x ] = ord.size ( ) ;
    for ( int i = 1 ; i < LOG ; ++ i ) {
        anc[ x ][ i ] = anc[ anc[ x ][ i - 1 ] ][ i - 1 ] ;
    }
    for ( auto y : v[ x ] ) {
        if ( y == prv ) { continue ; }
        lvl[ y ] = lvl[ x ] + 1 ;
        anc[ y ][ 0 ] = x ;
        dfs ( y , x ) ;
        ord.push_back ( x ) ;
    }
    en[ x ] = ord.size ( ) ;
}

int move_up ( int x , int cnt ) {
    for ( int i = LOG - 1 ; i >= 0 ; -- i ) {
        if ( cnt >= ( 1 << i ) ) {
            cnt -= ( 1 << i ) ;
            x = anc[ x ][ i ] ;
        }
    }
    return x ;
}

int get_lca ( int x , int y ) {
    int l = st[ x ] , r = st[ y ] ;
    if ( l > r ) { swap ( l , r ) ; }
    int len = r - l + 1 ;
    int id = pwid[ len ] ;
    int cand1 = rmq[ id ][ l ] , cand2 = rmq[ id ][ r - ( 1 << id ) + 1 ] ;
    if ( lvl[ cand1 ] <= lvl[ cand2 ] ) { return cand1 ; }
    return cand2 ;
}

int get_dist ( int x , int y ) {
    int aux = get_lca ( x , y ) ;
    return lvl[ x ] + lvl[ y ] - 2 * lvl[ aux ] ;
}

int used[ MAXN ] ;
int subtree[ MAXN ] , dep[ MAXN ] , mxdep[ MAXN ] ;
int cen_prv[ MAXN ] , cen_lvl[ MAXN ] ;
vector < int > sub_freq[ MAXN ] ;
vector < int > to_parent[ MAXN ] ;
int sub_freq_len[ MAXN ] ;
int vec_len[ MAXN ] ;

int tot_comp ;
void init ( int x , int prv ) {
    ++ tot_comp ;
    subtree[ x ] = 1 ;
    mxdep[ x ] = dep[ x ] ;
    for ( auto y : v[ x ] ) {
        if ( used[ y ] == 1 || y == prv ) { continue ; }
        dep[ y ] = dep[ x ] + 1 ;
        init ( y , x ) ;
        subtree[ x ] += subtree[ y ] ;
        mxdep[ x ] = max ( mxdep[ x ] , mxdep[ y ] ) ;
    }
}


int get_centroid ( int x , int prv ) {
    for ( auto y : v[ x ] ) {
        if ( used[ y ] == 1 || y == prv ) { continue ; }
        if ( 2 * subtree[ y ] > tot_comp ) {
            return get_centroid ( y , x ) ;
        }
    }
    return x ;
}
void add_up ( int x , int prv , int root , int type ) {
    if ( x <= small_n ) {
        if ( type == 0 ) { 
            ++ sub_freq[ root ][ dep[ x ] ] ;
        }
        else {
            ++ to_parent[ root ][ dep[ x ] ] ;
        }
    }
    for ( auto y : v[ x ] ) {
        if ( used[ y ] == 1 || y == prv ) { continue ; }
        add_up ( y , x , root , type ) ;
    }
}

void decompose ( int x , int prv , int wh ) {
    assert ( wh < LOG ) ;
    dep[ x ] = tot_comp = 0 ; init ( x , -1 ) ;
    x = get_centroid ( x , -1 ) ;
    used[ x ] = 1 ; cen_prv[ x ] = prv ; cen_lvl[ x ] = wh ; 
    dep[ x ] = tot_comp = 0 ; init ( x , -1 ) ;
    sub_freq[ x ].resize ( mxdep[ x ] + 1 , 0 ) ;
    sub_freq_len[ x ] = mxdep[ x ] ;
    add_up ( x , -1 , x , 0 ) ;
    for ( int i = 1 ; i <= mxdep[ x ] ; ++ i ) {
        sub_freq[ x ][ i ] += sub_freq[ x ][ i - 1 ] ;
    }
    for ( auto y : v[ x ] ) {
        if ( used[ y ] == 1 ) { continue ; }
        tot_comp = subtree[ y ] ;
        int nxt_cen = get_centroid ( y , x ) ;
        to_parent[ nxt_cen ].resize ( mxdep[ y ] + 1 , 0 ) ;
        vec_len[ nxt_cen ] = mxdep[ y ] ;
        add_up ( y , x , nxt_cen , 1 ) ;
        for ( int i = 1 ; i <= mxdep[ y ] ; ++ i ) {
            to_parent[ nxt_cen ][ i ] += to_parent[ nxt_cen ][ i - 1 ] ;
        }
    }
    for ( auto y : v[ x ] ) {
        if ( used[ y ] == 1 ) { continue ; }
        decompose ( y , x , wh + 1 ) ;
    }
}

int get_midway ( int x , int y ) {
    int aux = get_lca ( x , y ) ;
    int dist = get_dist ( x , y ) ;
    if ( lvl[ x ] - lvl[ aux ] >= dist / 2 ) {
        return move_up ( x , dist / 2 ) ;
    }
    else {
        return move_up ( y , dist / 2 ) ;
    }
}

int query ( int x , int mxdist ) {
    int aux = x , wh = cen_lvl[ x ] ;
    int ret = 0 , lst = 0 ;
    while ( aux > 0 ) {
        int hh = mxdist - get_dist ( x , aux ) ;
        if ( hh >= 0 ) {
            ret += sub_freq[ aux ][ min ( hh , sub_freq_len[ aux ] ) ] ;
            if ( lst > 0 ) {
                ret -= to_parent[ lst ][ min ( hh , vec_len[ lst ] ) ] ;
            }
        }
        lst = aux ;
        aux = cen_prv[ aux ] ;
        -- wh ;
    }
    return ret ;
}

void solve ( ) {
    cin >> n >> q ;
    small_n = n ;
    for ( int i = 1 ; i <= 2 * n ; ++ i ) {
        v[ i ].clear ( ) ;
        sub_freq[ i ].clear ( ) ;
        to_parent[ i ].clear ( ) ;
        sub_freq[ i ].shrink_to_fit ( ) ;
        to_parent[ i ].shrink_to_fit ( ) ;
        used[ i ] = 0 ;
    }
    for ( int i = 1 , x , y ; i < n ; ++ i ) {
        cin >> x >> y ;
        int aux = n + i ;
        v[ x ].push_back ( aux ) ;
        v[ aux ].push_back ( x ) ;
        v[ aux ].push_back ( y ) ;
        v[ y ].push_back ( aux ) ;
    }
    n = 2 * n - 1 ;
    ord.clear ( ) ;
    dfs ( 1 , -1 ) ;
    for ( int i = 1 ; i <= 2 * n - 1 ; ++ i ) {
        rmq[ 0 ][ i ] = ord[ i - 1 ] ;
    }
    for ( int k = 1 ; k < LOG ; ++ k ) {
        for ( int i = 1 ; i + ( 1 << k ) - 1 <= 2 * n - 1 ; ++ i ) {
            int cand1 = rmq[ k - 1 ][ i ] , cand2 = rmq[ k - 1 ][ i + ( 1 << ( k - 1 ) ) ] ;
            if ( lvl[ cand1 ] <= lvl[ cand2 ] ) { rmq[ k ][ i ] = cand1 ; }
            else { rmq[ k ][ i ] = cand2 ; }
        }
    }
    decompose ( 1 , -1 , 0 ) ;
    int lstans = 0 ;
    while ( q -- ) {
        int x , y , hh ;
        cin >> x >> y >> hh ;
        x = ( x + lstans ) % small_n + 1 , y = ( y + lstans ) % small_n + 1 , hh = ( hh + lstans ) % small_n ;
        hh *= 2 ;
        lstans = query ( x , hh ) + query ( y , hh ) ;
        int sr = get_dist ( x , y ) ;
        if ( sr <= 2 * hh ) {
            int mid = get_midway ( x , y ) ;
            // assert ( 1 <= mid && mid <= n ) ;
            lstans -= query ( mid , ( 2 * hh - sr ) / 2 ) ;
        }
        cout << lstans << "\n" ;
    }
}

int main ( ) {
    ios_base :: sync_with_stdio ( false ) ;
    cin.tie ( NULL ) ;
    for ( int i = 1 ; i < 2 * MAXN ; ++ i ) {
        pwid[ i ] = pwid[ i - 1 ] ;
        while ( ( 1 << pwid[ i ] ) * 2 < i ) { ++ pwid[ i ] ; }
    }
    int t = 1 ; cin >> t ;
    while ( t -- ) { solve ( ) ; }
    return 0 ;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 11681ms
memory: 115824kb

input:

100
100000 100000
67672 73429
73429 62807
36128 73429
73429 97696
26524 73429
94290 73429
30735 73429
51707 73429
73429 52862
29620 73429
73429 951
31570 73429
73429 93564
13195 73429
37473 73429
38853 73429
73871 73429
31884 73429
61635 73429
73429 74144
74632 73429
73429 34214
63517 73429
11989 73...

output:

3
3
3
3
3
2
3
3
2
3
3
2
2
3
2
2
2
2
2
2
2
2
2
2
2
3
2
2
2
2
2
3
3
3
3
2
3
3
2
3
2
2
3
3
3
3
2
3
3
2
3
2
2
2
3
2
3
3
2
3
2
3
3
2
3
3
2
2
3
3
3
2
2
2
3
3
3
3
3
3
2
3
2
2
3
3
3
3
3
2
2
3
2
3
2
2
3
2
3
3
3
2
2
3
3
2
3
3
2
2
3
2
2
3
2
2
2
3
3
3
2
3
2
2
2
3
3
2
2
3
2
2
3
2
2
2
3
3
3
2
2
3
3
3
3
3
2
2
2
3
...

result:

ok 1088007 lines