zoukankan      html  css  js  c++  java
  • BZOJ 1036: [ZJOI2008]树的统计Count

    二次联通门 : BZOJ 1036: [ZJOI2008]树的统计Count

    /*
        BZOJ 1036: [ZJOI2008]树的统计Count
    
        树链剖分板子题
    */
    #include <cstdio>
    #include <iostream>
    
    #define rg register
    #define Max 300007
    #define INF 1e8
    const int BUF = 12312331; char Buf[BUF], *buf = Buf;
    inline void read (int &n)
    {
        bool t = false;
        for (n = 0; !isdigit (*buf); ++ buf) if (*buf == '-') t = true;
        for (; isdigit (*buf); n = n * 10 + *buf - '0', ++ buf);
        if (t) n = -n;
    }
    struct E { E *n; int v; } *list[Max], poor[Max << 1], *Ta = poor;
    int N, in[Max], tk[Max], TC, key[Max];
    int GT ()
    {
        for (; (*buf) != 'Q' && (*buf) != 'C'; ++ buf);
        if (*(buf + 1) == 'M') return 2;
        else if (*(buf + 1) == 'S') return 1; return 3;
    }
    inline int min (int a, int b) { return a < b ? a : b; }
    inline int max (int a, int b) { return a > b ? a : b; }
    struct SD 
    { 
        SD *L, *R; int l, r, m, mx, s; 
        inline void Up () { mx = max (L->mx, R->mx), s = L->s + R->s; }
    } poorT[Max << 2 | 1], *TT = poorT;
    class SegmentTRee
    {
        private : SD *Root;
        
        private :
            
            inline SD* New (int _l, int _r)
            { 
                ++ TT, TT->L = TT->R = NULL; TT->mx = TT->s = 0; 
                TT->l = _l, TT->r = _r, TT->m = _l + _r >> 1; return TT; 
            }
            
            void Build (SD *&n, int l, int r)
            {
                n = New (l, r); if (l == r) { n->mx = n->s = tk[l];  return ; }
                Build (n->L, l, n->m), Build (n->R, n->m + 1, r); n->Up ();
            }
            
            void C (SD *&n, int p, int t)
            {
                if (n->l == n->r) { n->mx = n->s = t; return ; }
                if (p <= n->m) C (n->L, p, t); else C (n->R, p, t); n->Up ();
            }
            
            int Q (SD *&n, int l, int r, bool t)
            {
                if (l <= n->l && n->r <= r) { if (t) return n->s; return n->mx; } 
                int A, B; if (t) A = B = 0; else A = B = -INF; 
                if (l <= n->m) A = Q (n->L, l, r, t); if (r > n->m) B = Q (n->R, l, r, t);
                return t ? A + B : max (A, B);
            }
            
        public :
            
            void Build (int l, int r) { return Build (Root, l, r); }
            void C (int p, int t) { return C (Root, p, t); }
            int Q_max (int l, int r) { return Q (Root, l, r, false); }
            int Q_sum (int l, int r) { return Q (Root, l, r, true); }
    } Seg;
        
    inline void swap (int &a, int &b) { int c = a; a = b, b = c; }
    inline void cmax (int &a, int b) { if (b > a) a = b; }
    class TreeChain
    {
        private : int d[Max], s[Max], son[Max], c[Max], f[Max];
    
        private :
            
            void Dfs_1 (int n, int F)
            {
                s[n] = 1, d[n] = d[F] + 1, f[n] = F; int V;
                for (E *e = list[n]; e; e = e->n)
                    if ((V = e->v) != F)
                    {
                        Dfs_1 (V, n); s[n] += s[V];
                        if (s[son[n]] < s[V]) son[n] = V;
                    }
            }
            
            void Dfs_2 (int n, int C)
            {
                c[n] = C; in[n] = ++ TC, tk[TC] = key[n];
                if (son[n]) Dfs_2 (son[n], C); else return ; int V;
                for (E *e = list[n]; e; e = e->n)
                    if ((V = e->v) != f[n] && V != son[n]) Dfs_2 (V, V);
            }
            
            inline int Q (int x, int y, bool t)
            {
                int r; if (t) r = 0; else r = -INF;
                for (; c[x] != c[y]; x = f[c[x]])
                {
                    if (d[c[x]] < d[c[y]]) swap (x, y);
                    if (t) r += Seg.Q_sum (in[c[x]], in[x]);
                    else cmax (r, Seg.Q_max (in[c[x]], in[x]));
                }
                if (d[x] > d[y]) swap (x, y);
                return t ? (r + Seg.Q_sum (in[x], in[y])) : (max (r, Seg.Q_max (in[x], in[y])));
            }
            
        public :
            
            inline void Prepare () { Dfs_1 (1, 0), Dfs_2 (1, 1), Seg.Build (1, N); }
            inline void C (int p, int t) { return Seg.C (in[p], t); }
            inline int Q_max (int x, int y) { return Q (x, y, false); }
            inline int Q_sum (int x, int y) { return Q (x, y, true); }
    } T;
    
    int main (int argc, char *argv[])
    {
        fread (buf, 1, BUF, stdin); int i, j; int x, y; read (N);
        for (i = 1; i < N; ++ i)
        {
            read (x), read (y);
            ++ Ta, Ta->v = y, Ta->n = list[x], list[x] = Ta;
            ++ Ta, Ta->v = x, Ta->n = list[y], list[y] = Ta;
        }
        for (i = 1; i <= N; ++ i) read (key[i]);
        for (read (N), T.Prepare (); N; -- N)
        {
            i = GT (); read (x), read (y);
            if (i == 1) printf ("%d
    ", T.Q_sum (x, y));
            else if (i == 2) printf ("%d
    ", T.Q_max (x, y));
            else T.C (x, y);
        }
        return 0;
    }
  • 相关阅读:
    cocos2dx 3.x 集成protobuf
    Lua面向对象之三:其它一些尝试
    Lua面向对象之二:类继承
    Lua面向对象之一:简单例子
    cocos2dx lua 绑定之二:手动绑定自定义类中的函数
    向量点积、叉积的意义
    cocos2dx lua 绑定之一:自动绑定自定义类中的函数
    Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
    Lua和C++交互 学习记录之八:C++类注册为Lua模块
    Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/7587975.html
Copyright © 2011-2022 走看看