P4315 月下“毛景樹”
阿新 • • 發佈:2018-11-02
P4315 月下“毛景樹”
題目描述
毛毛蟲經過及時的變形,最終逃過的一劫,離開了菜媽的菜園。 毛毛蟲經過千山萬水,歷盡千辛萬苦,最後來到了小小的紹興一中的校園裡。
爬啊爬~爬啊爬毛毛蟲爬到了一顆小小的“毛景樹”下面,發現樹上長著他最愛吃的毛毛果~ “毛景樹”上有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之間樹枝上毛毛果個數最多有多少個。
Solution
樹剖
注意線段樹下推標記時分清楚對子節點標記的影響
Code
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #define LL long long #define REP(i, x, y) for(int i = (x);i <= (y);i++) using namespace std; int RD(){ int out = 0,flag = 1;char c = getchar(); while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();} while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();} return flag * out; } const int maxn = 100019,INF = 1e9 + 19; int head[maxn],nume = 1; struct Node{ int v,dis,nxt; }E[maxn << 3]; void add(int u,int v,int dis){ E[++nume].nxt = head[u]; E[nume].v = v; E[nume].dis = dis; head[u] = nume; } int num; int size[maxn], wson[maxn], dep[maxn], fa[maxn], val[maxn]; int top[maxn], pos[maxn], ori[maxn], tot; void dfs1(int u, int F){ size[u] = 1; for(int i = head[u];i;i = E[i].nxt){ int v = E[i].v; if(v == F)continue; val[v] = E[i].dis; dep[v] = dep[u] + 1; fa[v] = u; dfs1(v, u); size[u] += size[v]; if(size[v] > size[wson[u]])wson[u] = v; } } void dfs2(int u, int TP){ top[u] = TP; pos[u] = ++tot; ori[tot] = u; if(!wson[u])return ; dfs2(wson[u], TP); for(int i = head[u];i;i = E[i].nxt){ int v = E[i].v; if(v == fa[u] || v == wson[u])continue; dfs2(v, v); } } #define lid (id << 1) #define rid (id << 1) | 1 struct seg_tree{ int l, r; int max; int add, set; }tree[maxn << 2]; void pushup(int id){tree[id].max = max(tree[lid].max, tree[rid].max);} void build(int id, int l, int r){ tree[id].l = l, tree[id].r = r, tree[id].set = -1; if(l == r){ tree[id].max = val[ori[l]]; return ; } int mid = (l + r) >> 1; build(lid, l, mid), build(rid, mid + 1, r); pushup(id); } void pushdown(int id){ if(tree[id].set != -1){ int v = tree[id].set; tree[lid].max = tree[rid].max = v; tree[lid].set = tree[rid].set = v; tree[lid].add = tree[rid].add = 0; tree[id].add = 0; tree[id].set = -1; } if(tree[id].add != 0){ int v = tree[id].add; tree[lid].max += v; tree[rid].max += v; if(tree[lid].set != -1)tree[lid].set += v; if(tree[rid].set != -1)tree[rid].set += v; tree[lid].add += v; tree[rid].add += v; tree[id].add = 0; } } void update(int id, int v, int l, int r, int o){ pushdown(id); if(tree[id].l == l && tree[id].r == r){ if(o == 1){//1為全改變 tree[id].max = v; tree[id].set = v; } else{//0為區間加 tree[id].max += v; tree[id].add += v; } return ; } int mid = (tree[id].l + tree[id].r) >> 1; if(mid < l)update(rid, v, l, r, o); else if(mid >= r)update(lid, v, l, r, o); else update(lid, v, l, mid, o), update(rid, v, mid + 1, r, o); pushup(id); } int query(int id, int l, int r){ pushdown(id); if(tree[id].l == l && tree[id].r == r)return tree[id].max; int mid = (tree[id].l + tree[id].r) >> 1; if(mid < l)return query(rid, l, r); else if(mid >= r)return query(lid, l, r); else return max(query(lid, l, mid), query(rid, mid + 1, r)); } void uprange(int x, int y, int v, int o){ while(top[x] != top[y]){ if(dep[top[x]] < dep[top[y]])swap(x, y); update(1, v, pos[top[x]], pos[x], o); x = fa[top[x]]; } if(x == y)return ; if(dep[x] > dep[y])swap(x, y); update(1, v, pos[x] + 1, pos[y], o); } int Q_max(int x, int y){ int ret = 0; while(top[x] != top[y]){ if(dep[top[x]] < dep[top[y]])swap(x, y); ret = max(ret, query(1, pos[top[x]], pos[x])); x = fa[top[x]]; } if(x == y)return ret; if(dep[x] > dep[y])swap(x, y); ret = max(ret, query(1, pos[x] + 1, pos[y])); return ret; } struct EDG{int x, y;}I[maxn]; void init(){ num = RD(); REP(i, 1, num - 1){ int u = RD(), v = RD(), dis = RD(); I[i] = (EDG){u, v}; add(u, v, dis), add(v, u, dis); } dep[1] = 1; dfs1(1, -1); dfs2(1, 1); build(1, 1, num); } void solve(){ char cmd[19]; while(1){ scanf("%s", cmd); if(cmd[0] == 'S')return ; else if(cmd[0] == 'C' && cmd[1] == 'h'){ int k = RD(), w = RD(); uprange(I[k].x, I[k].y, w, 1); } else if(cmd[0] == 'C' && cmd[1] == 'o'){ int x = RD(), y = RD(), w = RD(); uprange(x, y, w, 1); } else if(cmd[0] == 'A'){ int x = RD(), y = RD(), w = RD(); uprange(x, y, w, 0); } else{ int x = RD(), y = RD(); printf("%d\n", Q_max(x, y)); } } } int main(){ init(); solve(); return 0; }