分治专题

来源:互联网 发布:java身份证号判断性别 编辑:程序博客网 时间:2024/06/07 00:25

涉及题目: poj2299  //http://poj.org/problem?id=2299

                  poj1741 //http://poj.org/problem?id=1741


数列分治

复杂度O(nlogn)

#include <cstdio>#include <cstring>#include <iostream>#include <vector>using namespace std ;typedef long long ll ;vector <int> A ;ll merge_count( vector<int> & a){    int n = a.size() ;    if( n <= 1 ) return 0 ;    ll cnt = 0 ;    vector<int> b(a.begin() , a.begin() + n/2);    vector<int> c(a.begin() + n/2 , a.end());    cnt += merge_count(b) ;    cnt += merge_count(c) ;    // b c have been sorted    int ai = 0 , bi = 0 , ci = 0 ;    while( ai < n ){        if( bi < b.size() && (ci == c.size() || b[bi] <= c[ci])){            a[ai ++] = b[bi ++];        }else{            cnt += n/2 - bi ;            a[ai ++] = c[ci ++ ];        }    }    return cnt ;}void solve(vector<int> & A){    ll ans = merge_count(A) ;    printf("%lld\n" , ans) ;}vector<int> save ;int main(){    int n ,a ;    while( ~ scanf("%d",&n) && n ){        save.clear() ;        for(int i = 0 ; i < n ; i ++ ){            scanf("%d" , &a);            save.push_back( a ) ;        }        solve(save) ;    }    return 0 ;}




树形分治


    对于这道题目

   O(n log2 n) ;

#include <cstdio>#include <cstring>#include <iostream>#include <vector>#include <algorithm>using namespace std ;typedef long long ll ;const int MAX_N = 10000+5 ;const int INT_MAX = 100000000+7 ;struct edge{    int to , length  ;};int N , K ;vector<edge> G[MAX_N] ;bool centroid[MAX_N] ;int subtree_size[MAX_N] ;int ans ;int compute_subtree_size( int v , int p ){    int c = 1 ;    for( int i = 0 ; i < G[v].size() ; i ++ ){        int w = G[v][i].to ;        if(w == p || centroid[w]) continue ;        c += compute_subtree_size( w , v ) ;    }    subtree_size[v] = c ;    return c ;}pair<int , int > search_centroid(int v , int p , int t){    pair<int , int > res  = make_pair(INT_MAX , -1 ) ;    int s = 1 , m = 0 ;    for( int i = 0 ; i < G[v].size() ; i ++ ){        int w = G[v][i].to ;        if( w == p || centroid[w]) continue ;        res = min(res , search_centroid(w , v , t)) ;        m = max(m , subtree_size[w] ) ;        s += subtree_size[w] ;    }    m = max( m , t - s );    res = min( res , make_pair(m , v )) ;    return res ;}void enumerate_paths( int v , int p , int d , vector<int> &ds ){    ds.push_back(d) ;    for( int i = 0 ; i < G[v].size() ; i ++ ){        int w = G[v][i].to ;        if( w == p || centroid[w] ) continue ;        enumerate_paths(w , v , d + G[v][i].length , ds) ;    }}int count_pairs(vector<int> &ds){    int res = 0 ;    sort( ds.begin() , ds.end()) ;    int j = ds.size() ;    for(int i = 0 ; i < ds.size() ; i ++ ){        while( j > 0 && ds[i] + ds[j-1] > K ) -- j ;        res += j - ( j > i ? 1 : 0 ) ;    }    return res / 2 ;}void solve_subproblem(int v ){    compute_subtree_size(v , -1) ;    int s = search_centroid( v , -1 , subtree_size[v]).second ;    centroid[s] = true ;    for( int i = 0 ; i < G[s].size() ; i ++) {        if(centroid[ G[s][i].to]) continue ;        solve_subproblem( G[s][i].to );    }    vector<int> ds ;    ds.push_back(0) ;    for( int i = 0 ; i < G[s].size() ; i ++ ){        if( centroid[G[s][i].to]) continue ;        vector<int> tds ;        enumerate_paths(G[s][i].to , s , G[s][i].length , tds) ;        ans -= count_pairs(tds) ;        ds.insert(ds.end() , tds.begin() , tds.end()) ;    }    ans += count_pairs(ds) ;    centroid[s] = false ;}void solve(){    ans = 0 ;    solve_subproblem(0) ;    printf("%d\n" , ans );}int main(){    int n  ;    while( ~ scanf("%d %d",&N , &K)  ){        if( !N && !K) break ;        for( int i = 0 ; i <= N ; i ++ ) G[i].clear() ;        memset( centroid , 0 , sizeof( centroid )) , memset(subtree_size , 0 , sizeof(subtree_size)) ;        int a , b , c;        edge temp ;        for(int i = 0 ; i < N - 1  ; i ++ ){            scanf("%d %d %d" , &a , &b , &c);            a -- , b -- ;            temp.length = c , temp.to = b ;            G[a].push_back(temp) ;            temp.to = a ;            G[b].push_back(temp) ;        }        solve() ;    }    return 0 ;}


原创粉丝点击