[SDOI2011]染色

[SDOI2011]染色

简化题意 (:)

给定一棵点带权的树,维护两种操作 (:)

1.把 ((x,y)) 这条链上的点权全部置为 (w).
2.查询 ((x,y)) 这条链上有多少不同的点权.

树剖 (+) 线段树维护即可.

线段树维护覆盖标记,权值个数和左端点右端点的权值.

向上合并的时候判断,左儿子的右端点权值和右儿子的左端点权值是否相同,如果相同就 (-1) .

查询的时候,合并左右儿子查询上来的信息时也要类似处理.

这样线段树的问题就解决了.

那么做完了嘛 (?)

没有,你发现树剖跳链的时候也会有合并问题.

那怎么办呢 (?) 由于树剖跳链是两边跳,所以你需要分别维护每一边的最后一个权值是什么,再下一次跳链的时候判断是否和上一次重复即可.(充分利用树剖 (+) 线段树的结构性质).

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
#define MEM(x,y) memset ( x , y , sizeof ( x ) )
#define rep(i,a,b) for (int i = (a) ; i <= (b) ; ++ i)
#define per(i,a,b) for (int i = (a) ; i >= (b) ; -- i)
#define pii pair < int , int >
#define one first
#define two second
#define rint read<int>
#define int long long
#define pb push_back
#define db double
#define ull unsigned long long
#define lowbit(x) ( x & ( - x ) )

using std::queue ;
using std::set ;
using std::pair ;
using std::max ;
using std::min ;
using std::priority_queue ;
using std::vector ;
using std::swap ;
using std::sort ;
using std::unique ;
using std::greater ;

template < class T >
    inline T read () {
        T x = 0 , f = 1 ; char ch = getchar () ;
        while ( ch < '0' || ch > '9' ) {
            if ( ch == '-' ) f = - 1 ;
            ch = getchar () ;
        }
       while ( ch >= '0' && ch <= '9' ) {
            x = ( x << 3 ) + ( x << 1 ) + ( ch - 48 ) ;
            ch = getchar () ;
       }
       return f * x ;
    }

const int N = 1e6 + 100 ;

vector < int > G[N] ;
int n , m , v[N] , siz[N] , idx[N] , w[N] ;
int deep[N] , son[N] , top[N] , f[N] , cnt ;
int L , R , color_l , color_r ;

class Tree {
    #define mid ( ( l + r ) >> 1ll )
    private : struct seg { int ls , rs , data , lc , rc , tag ; } t[N<<1] ;
    private : int num ;
    public :
        inline void clear () { num = 1 ; return ; }
    private :
        inline void pushup (int rt) {
            t[rt].lc = t[t[rt].ls].lc ; t[rt].rc = t[t[rt].rs].rc ;
            t[rt].data = t[t[rt].ls].data + t[t[rt].rs].data ;
            if ( t[t[rt].ls].rc == t[t[rt].rs].lc ) -- t[rt].data ;
            return ;
        }
    public :
        inline void build (int rt , int l , int r) {
            t[rt].tag = 0 ;
            if ( l == r ) { t[rt].data = 1ll ; t[rt].lc = t[rt].rc = w[l] ; return ; }
            t[rt].ls = ++ num ; build ( t[rt].ls , l , mid ) ;
            t[rt].rs = ++ num ; build ( t[rt].rs , mid + 1 , r ) ;
            pushup ( rt ) ; return ;
        }
    private :
        inline void pushdown (int rt) {
            t[t[rt].ls].tag = t[t[rt].rs].tag = t[rt].tag ;
            t[t[rt].ls].data = t[t[rt].rs].data = 1ll ;
            t[t[rt].ls].lc = t[t[rt].ls].rc = t[rt].tag ;
            t[t[rt].rs].lc = t[t[rt].rs].rc = t[rt].tag ;
            t[rt].tag = 0 ; return ;
        }
    public :
        inline void cover (int rt , int l , int r , int ll , int rr , int key) {
            if ( l == ll && r == rr ) {
                t[rt].data = 1ll ; t[rt].tag = key ;
                t[rt].lc = t[rt].rc = key ; return ;
            }
            if ( t[rt].tag ) pushdown ( rt ) ;
            if ( rr <= mid ) cover ( t[rt].ls , l , mid , ll , rr , key ) ;
            else if ( ll > mid ) cover ( t[rt].rs , mid + 1 , r , ll , rr , key ) ;
            else cover ( t[rt].ls , l , mid , ll , mid , key ) , cover ( t[rt].rs , mid + 1 , r , mid + 1 , rr , key ) ;
            pushup ( rt ) ; return ;
        }
    public :
        inline int query (int rt , int l , int r , int ll , int rr) {
            if ( l == L ) color_l = t[rt].lc ;
            if ( r == R ) color_r = t[rt].rc ;
            if ( l == ll && r == rr ) return t[rt].data ;
            if ( t[rt].tag ) pushdown ( rt ) ;
            if ( rr <= mid ) return query ( t[rt].ls , l , mid , ll , rr ) ;
            else if ( ll > mid ) return query ( t[rt].rs , mid + 1 , r , ll , rr ) ;
            else {
                int res = query ( t[rt].ls , l , mid , ll , mid ) + query ( t[rt].rs , mid + 1 , r , mid + 1 , rr ) ;
                if ( t[t[rt].ls].rc == t[t[rt].rs].lc ) -- res ; return res ;
            }
        }
    #undef mid
} T ;

inline void dfs (int cur , int anc , int dep) {
    siz[cur] = 1 ; f[cur] = anc ; deep[cur] = dep ;
    int maxson = - 1 ;  for (int k : G[cur]) {
        if ( k == anc ) continue ;
        dfs ( k , cur , dep + 1 ) ; siz[cur] += siz[k] ;
        if ( siz[k] > maxson ) maxson = siz[k] , son[cur] = k ;
    }
    return ;
}

inline void _dfs (int cur , int topf) {
    top[cur] = topf ; idx[cur] = ++ cnt ; w[cnt] = v[cur] ;
    if ( ! son[cur] ) return ; _dfs ( son[cur] , topf ) ;
    for (int k : G[cur] ) {
        if ( k == f[cur] || k == son[cur] ) continue ;
        _dfs ( k , k ) ;
    }
    return ;
}

inline void uprange (int x , int y , int key) {
    while ( top[x] != top[y] ) {
        if ( deep[top[x]] < deep[top[y]] ) swap ( x , y ) ;
        T.cover ( 1 , 1 , cnt , idx[top[x]] , idx[x] , key ) ;
        x = f[top[x]] ;
    }
    if ( deep[x] > deep[y] ) swap ( x , y ) ;
    T.cover ( 1 , 1 , cnt , idx[x] , idx[y] , key ) ;
    return ;
}

inline int qrange (int x , int y) {
    int res = 0 , lastx = - 1 , lasty = - 1 ;
    while ( top[x] != top[y] ) {
        if ( deep[top[x]] < deep[top[y]] )
            swap ( x , y ) , swap ( lastx , lasty ) ;
        L = idx[top[x]] ; R = idx[x] ;
        res += T.query ( 1 , 1 , cnt , idx[top[x]] , idx[x] ) ;
        if ( color_r == lastx ) -- res ; lastx = color_l ;
        x = f[top[x]] ;
    }
    if ( deep[x] > deep[y] ) swap ( x , y ) , swap ( lastx , lasty ) ;
    L = idx[x] ; R = idx[y] ;
    res += T.query ( 1 , 1 , cnt , idx[x] , idx[y] ) ;
    if ( color_l == lastx ) -- res ;
    if ( color_r == lasty ) -- res ;
    return res ;
}

signed main (int argc , char * argv[]) {
    n = rint () ; m = rint () ;
    rep ( i , 1 , n ) v[i] = rint () ;
    rep ( i , 2 , n ) {
        int u = rint () , v = rint () ;
        G[u].pb ( v ) ; G[v].pb ( u ) ;
    }
    dfs ( 1 , 0 , 1 ) ; _dfs ( 1 , 1 ) ;
    T.clear () ; T.build ( 1 , 1 , cnt ) ;
    char opt[3] ;
    while ( m -- ) {
        scanf ("%s" , opt ) ;
        int x = rint () , y = rint () ;
        if ( opt[0] == 'C' ) {
            int z = rint () ;
            uprange ( x , y , z ) ;
        } else printf ("%lld
" , qrange ( x , y ) ) ;
    }
    #ifndef ONLINE_JUDGE
    system ("pause") ;
    #endif
    return 0 ;
}
原文地址:https://www.cnblogs.com/Equinox-Flower/p/11756735.html