1. 程式人生 > >CF600E Lomsat gelral 【線段樹合並】

CF600E Lomsat gelral 【線段樹合並】

ems urn fine lse 兩個 ring esp return str

題目鏈接

CF600E

題解

容易想到就是線段樹合並,維護每個權值區間出現的最大值以及最大值位置之和即可
對於每個節點合並一下兩個子節點的信息
要註意葉子節點信息的合並和非葉節點信息的合並是不一樣的

由於合並不比逐個插入復雜度高,所以應是\(O(nlogn)\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++) #define mp(a,b) make_pair<int,int>(a,b) #define cls(s) memset(s,0,sizeof(s)) #define cp pair<int,int> #define LL long long int using namespace std; const int maxn = 100005,maxm = 8000005,INF = 1000000000; inline int read(){ int out = 0,flag = 1; char c = getchar(); while
(c < 48 || c > 57){if (c == ‘-‘) flag = -1; c = getchar();} while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();} return out * flag; } LL sum[maxm],ans[maxn]; int ls[maxm],rs[maxm],mx[maxm],cnt; int n,c[maxn],fa[maxn],rt[maxn]; int
h[maxn],ne = 1; struct EDGE{int to,nxt;}ed[maxn << 1]; inline void build(int u,int v){ ed[++ne] = (EDGE){v,h[u]}; h[u] = ne; ed[++ne] = (EDGE){u,h[v]}; h[v] = ne; } inline void upd(int u){ sum[u] = 0; if (mx[ls[u]] >= mx[rs[u]]){ mx[u] = mx[ls[u]]; sum[u] += sum[ls[u]]; } if (mx[rs[u]] >= mx[ls[u]]){ mx[u] = mx[rs[u]]; sum[u] += sum[rs[u]]; } } void modify(int& u,int pre,int l,int r,int pos){ u = ++cnt; ls[u] = ls[pre]; rs[u] = rs[pre]; if (l == r){mx[u] = mx[pre] + 1; sum[u] = l; return;} int mid = l + r >> 1; if (mid >= pos) modify(ls[u],ls[pre],l,mid,pos); else modify(rs[u],rs[pre],mid + 1,r,pos); upd(u); } int merge(int u,int v,int l,int r){ if (!u) return v; if (!v) return u; int t = ++cnt,mid = l + r >> 1; if (l == r){ mx[t] = mx[u] + mx[v]; sum[t] = l; return t; } ls[t] = merge(ls[u],ls[v],l,mid); rs[t] = merge(rs[u],rs[v],mid + 1,r); upd(t); return t; } void dfs(int u){ modify(rt[u],rt[u],1,n,c[u]); Redge(u) if ((to = ed[k].to) != fa[u]){ fa[to] = u; dfs(to); rt[u] = merge(rt[u],rt[to],1,n); } ans[u] = sum[rt[u]]; } int main(){ n = read(); REP(i,n) c[i] = read(); for (int i = 1; i < n; i++) build(read(),read()); dfs(1); REP(i,n) printf("%lld ",ans[i]); return 0; }

CF600E Lomsat gelral 【線段樹合並】