zoukankan      html  css  js  c++  java
  • BZOJ 1984月下“毛景树” LCT维护边权 + 下传标记

    Description

    毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

    Input

    第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

    Output

    对于毛毛虫的每个询问操作,输出一个答案。

    题解:树剖太简单了,练一练 LCT

    #include <bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin) 
    #define maxn 100050 
    #define inf 0x3f 
    using namespace std;
    int n; 
    char str[10]; 
    namespace LCT
    {
        #define lson ch[x][0] 
        #define rson ch[x][1] 
        int maxv[maxn << 1], tag[maxn << 1], rev[maxn << 1], addv[maxn << 1], val[maxn << 1], siz[maxn << 1], f[maxn << 1], sta[maxn << 1], ch[maxn << 1][2]; 
    
        int isRoot(int x) 
        { 
            return !(ch[f[x]][0] == x || ch[f[x]][1] == x); 
        }      
        int get(int x) 
        { 
            return ch[f[x]][1] == x; 
        }          
        void mark_tag(int x, int delta)
        {
            if(!x) return;  
            addv[x] = 0; 
            tag[x] = (siz[x] ? delta : 0);        
            maxv[x] = (siz[x] ? delta : 0); 
            if(x > n) val[x] = delta; 
        }
        void mark_add(int x, int delta)
        {
            if(!x) return;    
            addv[x] += (siz[x] ? delta : 0);       
            maxv[x] += (siz[x] ? delta : 0); 
            if(x > n) val[x] += delta; 
        }
        void mark_rev(int x) 
        {
            if(!x) return; 
            swap(lson, rson), rev[x] ^= 1;          
        }
        void pushup(int x)
        {                  
            maxv[x] = max(val[x], max(maxv[lson], maxv[rson])); 
            siz[x] = (x > n) + siz[lson] + siz[rson];       
        }
        void pushdown(int x)
        {     
            if(tag[x])  mark_tag(lson, tag[x]), mark_tag(rson, tag[x]), tag[x] = 0;
            if(addv[x]) mark_add(lson, addv[x]), mark_add(rson, addv[x]), addv[x] = 0; 
            if(rev[x])  mark_rev(lson), mark_rev(rson), rev[x] = 0; 
        }
        void rotate(int x)
        {
            int old = f[x], fold = f[old], which = get(x); 
            if(!isRoot(old)) ch[fold][ch[fold][1] == old] = x; 
            ch[old][which] = ch[x][which ^ 1], f[ch[old][which]] = old; 
            ch[x][which ^ 1] = old, f[old] = x, f[x] = fold; 
            pushup(old), pushup(x); 
        }
        void splay(int x)
        {
            int u = x, v = 0; 
            sta[++v] = u; 
            while(!isRoot(u)) sta[++v] = f[u], u = f[u]; 
            while(v) pushdown(sta[v--]);     
            u = f[u]; 
            for(int fa; (fa = f[x]) != u; rotate(x)) 
                if(f[fa] != u) rotate(get(fa) == get(x) ? fa : x); 
        }
        void Access(int x)
        {
            int y = 0; 
            while(x) splay(x), rson = y, pushup(x), y = x, x = f[x]; 
        }
        void MakeRoot(int x)
        {
            Access(x), splay(x), mark_rev(x);  
        }
        // y is new root 
        void split(int x, int y)
        {
            MakeRoot(x), Access(y), splay(y); 
        }
        void link(int x, int y)
        { 
            MakeRoot(y), f[y] = x; 
        }
    };   
    int main()
    {
        // setIO("input"); 
        LCT :: maxv[0] = -inf; 
        scanf("%d",&n); 
        for(int i = 1; i < n; ++i) 
        {
            int u, v, w; 
            scanf("%d%d%d",&u,&v,&w);                      
            LCT :: val[i + n] = w;  
            LCT :: link(u, i + n); 
            LCT :: link(i + n, v);  
        }
        while(1) 
        {
            scanf("%s",str); 
            int u, v, k, w; 
            if(str[0] == 'A') 
            {
                scanf("%d%d%d",&u,&v,&w), LCT :: split(u, v), LCT :: mark_add(v, w); 
            }
            if(str[0] == 'M')
            {
                scanf("%d%d",&u,&v), LCT :: split(u, v), printf("%d
    ",LCT :: maxv[v]); 
            }
            if(str[1] == 'o') 
            {
                scanf("%d%d%d",&u,&v,&w), LCT :: split(u, v), LCT :: mark_tag(v, w); 
            }
            if(str[1] == 'h') 
            {    
                scanf("%d%d",&k,&w);
                LCT :: Access(k + n), LCT :: splay(k + n), LCT :: val[k + n] = w, LCT :: pushup(k + n);       
            }
            if(str[0] == 'S') break; 
        }
        return 0; 
    }
    

      

  • 相关阅读:
    android 休眠唤醒机制分析(三) — suspend
    android 休眠唤醒机制分析(一) — wake_lock
    开机音乐不发声的问题
    Linux的时钟管理
    Android4.2增加新键值
    _IO, _IOR, _IOW, _IOWR 宏的用法与解析
    Mifare 0简介
    Mifare 1卡的存储结构
    Maven 介绍
    DAL 层引用 System.Net.Http ,引发的一阵心慌
  • 原文地址:https://www.cnblogs.com/guangheli/p/10981482.html
Copyright © 2011-2022 走看看