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)<<'\n';
            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
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章