zoukankan      html  css  js  c++  java
  • [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 ;
    }
    
  • 相关阅读:
    解决软件升级过程中GAC发生的问题.
    Appupdater 组件的一个问题.
    == 和 != 有点靠不主,建议在进行比较的时候尽可能的使用Equals
    从资源文件中提取Icon对象到Image对象的小技巧。
    arcgis flex开发备忘
    IIS服务器的系统事件日志常见问题汇总(更新中)
    WebSphere6.1配置应用程序
    Android Preference使用
    Oracle无法删除当前已连接的用户
    SSH环境搭建
  • 原文地址:https://www.cnblogs.com/Equinox-Flower/p/11756735.html
Copyright © 2011-2022 走看看