• Poj3237 树刨+线段树(边权转点权)


    题意:在树上操作,每次将两点路径值全变负和单点修改。每次求两点间路径的最大值。
    思路:
    边权转点权的话,每次把一条边的儿子点作为该边的权值。想起来挺好想,很容易出问题。
    查询修改的话,要将多算的那条lca去掉就可以了。剩下的就是板子。
    总结:

    1. 去掉lca,只需要判断top[x]==top[y]时,x和y是否相等,不等把deep浅的点+1即可。
    2. 边权转点权,因为你不知道谁是谁的父亲,所以要树刨完或者第一遍dfs完建点权和树,单点修改也是。
      代码:
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<cstring>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #include<cmath>
    #include<sstream>
    using namespace std;
    #define ll long long
    #define forn(i,n) for(int i=0;i<n;i++)
    #define for1(i,n) for(int i=1;i<=n;i++)
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    const int maxn = 1e4+5;
    const int inf = 0x3f3f3f3f;
    int a[maxn],top[maxn],p[maxn],sz[maxn],par[maxn],son[maxn],deep[maxn],fp[maxn],id,now;
    pair<pair<int,int>,int>g[maxn];
    vector<int>e[maxn];
    class segment_tree{
        public:
        #define nd node[now]
        #define ndl node[now<<1]
        #define ndr node[now<<1|1]
        struct segment_node{
            int l,r,v,V,flag;
            void update(){
                flag^=1;
                v=-v,V=-V;
                swap(v,V);
            }
        }node[maxn<<2];
        void pushup(int now){
            nd.v = min(ndl.v,ndr.v);
            nd.V = max(ndl.V,ndr.V);
        }
        void pushdown(int now){
            if(nd.flag){
                ndl.update();
                ndr.update();
                nd.flag = 0;
            }
        }
        void maketree(int l,int r,int now = 1){
            nd = {l,r,0,0,0};
            if(l==r){
                nd.v = nd.V = a[fp[l]];
                return;
            }
            maketree(l,l+r>>1,now<<1);
            maketree((l+r>>1)+1,r,now<<1|1);
            pushup(now);        
        }
        void update(int pos,int v,int now = 1){
            if(nd.l==nd.r){
                nd.v = nd.V = v;
                return;
            }
            pushdown(now);
            if(pos<=ndl.r) update(pos,v,now<<1);
            else update(pos,v,now<<1|1);
            pushup(now);
        }
        void update2(int l,int r,int now = 1){
            if(l<=nd.l&&r>=nd.r){
                nd.update();
                return;
            }
            pushdown(now);
            if(l<=ndl.r) update2(l,r,now<<1);
            if(r>=ndr.l) update2(l,r,now<<1|1);
            pushup(now);
        }
        int query(int l,int r,int now = 1){
            if(l<=nd.l&&r>=nd.r) return nd.V;
            pushdown(now);
            int res = -inf;
            if(l<=ndl.r) res = max(res,query(l,r,now<<1));
            if(r>=ndr.l) res = max(res,query(l,r,now<<1|1));
            pushup(now);
            return res;
        }
    }tree;
    void dfs(int u,int pre,int d){
        deep[u] = d,par[u] = pre,sz[u] = 1;
        forn(i,e[u].size()){
            int v = e[u][i];
            if(v==pre) continue;
            dfs(v,u,d+1);
            sz[u]+=sz[v];
            if(sz[v]>sz[son[u]]) son[u] = v;
        }
    }
    void getpos(int u,int gg){
        top[u] = gg,p[u] = ++id,fp[p[u]] = u;
        if(son[u]) getpos(son[u],gg);
        forn(i,e[u].size()){
            int v = e[u][i];
            if(v==par[u]||v==son[u]) continue;
            getpos(v,v);
        }
    }
    void init(){
        id = 0;
        forn(i,maxn){
            e[i].clear();
            son[i] = 0;
        }
    }
    int Q(int x,int y){
        int fx = top[x],fy = top[y],res = -inf;
        while(fx!=fy){
            if(deep[fx]<deep[fy]) swap(fx,fy),swap(x,y);
            res = max(res,tree.query(p[fx],p[x]));
            x = par[fx],fx = top[x];
        }
        if(x!=y){
            if(deep[x]>deep[y]) swap(x,y);
            res = max(res,tree.query(p[x]+1,p[y]));
        }
        return res;
    }
    void change(int x,int y){
        int fx = top[x],fy = top[y];
        while(fx!=fy){
            if(deep[fx]<deep[fy]) swap(fx,fy),swap(x,y);
            tree.update2(p[fx],p[x]);
            x = par[fx],fx = top[x];
        }
        if(x!=y){
            if(deep[x]>deep[y]) swap(x,y);
            tree.update2(p[x]+1,p[y]);
        }
    }
    
    int main(){
        IO;
        int t;cin>>t;
        while(t--){
            init();
            int n;cin>>n;
            for1(i,n-1){
                int x,y,z;cin>>x>>y>>z;
                g[i] = {{x,y},z};
                e[x].push_back(y);
                e[y].push_back(x);
            }
            dfs(1,0,0);
            getpos(1,0);
            for1(i,n-1){
                if(par[g[i].first.first]==g[i].first.second) a[g[i].first.first] = g[i].second;
                else a[g[i].first.second] = g[i].second; 
            }
            tree.maketree(1,n);
            string s;
            while(cin>>s){
                if(s[0]=='D') break;
                int x,y;cin>>x>>y;
                if(s[0]=='Q') cout<<Q(x,y)<<'
    ';
                else if(s[0]=='C') tree.update(p[(par[g[x].first.first]==g[x].first.second?g[x].first.first:g[x].first.second)],y);
                else change(x,y);
            }
        }
        return 0;
    }
    /*
    3
    6
    1 2 2
    1 3 1
    3 4 3
    3 5 4
    5 6 5
    Q 4 5
    Q 1 3
    N 4 5
    Q 4 5
    Q 5 4
    Q 1 3
    C 4 1
    Q 4 5
    Q 5 4
    Q 1 3
    D
    */
    
  • 相关阅读:
    关于Java常见的误解
    Java程序设计概述
    是结束,更是开始!
    从零开始单排学设计模式「简单工厂设计模式」黑铁 III
    某神秘公司 RESTful、共用接口、前后端分离、接口约定的实践
    这40张图送给单身程序员,情人节请一笑而过!
    科技圈晒开工福利!2019一起定个小目标!
    IDEA一定要懂的32条快捷键
    假期结束了,我相信未来会更好!
    有一种痛,叫 “今年没有年终奖”!!!
  • 原文地址:https://www.cnblogs.com/AlexPanda/p/12520302.html
Copyright © 2020-2023  润新知