#pragma GCC target ("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using ll = long long; using ld = long double; using H = pair; using P = pair; using vi = vector; #define all(a) (a).begin(),(a).end() #define fs first #define sc second #define xx first #define yy second.first #define zz second.second #define Q(i,j,k) mkp(i,mkp(j,k)) #define rng(i,s,n) for(ll i = (s) ; i < (n) ; i++) #define rep(i,n) rng(i, 0, (n)) #define mkp make_pair #define vec vector #define pb emplace_back #define siz(a) (int)(a).size() #define crdcomp(b) sort(all((b)));(b).erase(unique(all((b))),(b).end()) #define getidx(b,i) (lower_bound(all(b),(i))-(b).begin()) #define ssp(i,n) (i==(ll)(n)-1?"\n":" ") #define ctoi(c) (int)(c-'0') #define itoc(c) (char)(c+'0') #define cyes printf("Yes\n") #define cno printf("No\n") #define cdf(n) for(int quetimes_=(n);quetimes_>0;quetimes_--) #define gcj printf("Case #%lld: ",qq123_+1) #define readv(a,n) a.resize(n,0);rep(i,(n)) a[i]=read() #define found(a,x) (a.find(x)!=a.end()) constexpr ll mod = (ll)1e9 + 7; constexpr ll Mod = 998244353; constexpr ld EPS = 1e-10; constexpr ll inf = (ll)3 * 1e18; constexpr int Inf = (ll)15 * 1e8; constexpr int dx[] = { -1,1,0,0 }, dy[] = { 0,0,-1,1 }; templatebool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; } templatebool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; } ll read() { ll u, k = scanf("%lld", &u); return u; } string reads() { string s; cin >> s; return s; } H readh(short g = 0) { H u; int k = scanf("%lld %lld", &u.fs, &u.sc); if (g == 1) u.fs--, u.sc--; if (g == 2) u.fs--; return u; } bool ina(H t, int h, int w) { return 0 <= t.fs && t.fs < h && 0 <= t.sc && t.sc < w; } bool ina(int t, int l, int r) { return l <= t && t < r; } ll gcd(ll i, ll j) { return j ? gcd(j, i % j) : i; } ll popcount(ll x) { int sum = 0; for (int i = 0; i < 60; i++)if ((1ll << i) & x) sum++; return sum; } template class csum { vec v; public: csum(vec& a) :v(a) { build(); } csum() {} void init(vec& a) { v = a; build(); } void build() { for (int i = 1; i < v.size(); i++) v[i] += v[i - 1]; } //[l,r] T a(int l, int r) { if (r < l) return 0; return v[r] - (l == 0 ? 0 : v[l - 1]); } //[l,r) T b(int l, int r) { return a(l, r - 1); } T a(pairt) { return a(t.first, t.second); } T b(pairt) { return b(t.first, t.second); } }; class mint { public:ll v; mint(ll v = 0) { s(v % mod + mod); } constexpr static int mod = (ll)1e9 + 7; constexpr static int fn_ = (ll)2e6 + 5; static mint fact[fn_], comp[fn_]; mint pow(int x) const { mint b(v), c(1); while (x) { if (x & 1) c *= b; b *= b; x >>= 1; } return c; } inline mint& s(int vv) { v = vv < mod ? vv : vv - mod; return *this; } inline mint inv()const { return pow(mod - 2); } inline mint operator-()const { return mint() - *this; } inline mint& operator+=(const mint b) { return s(v + b.v); } inline mint& operator-=(const mint b) { return s(v + mod - b.v); } inline mint& operator*=(const mint b) { v = v * b.v % mod; return *this; } inline mint& operator/=(const mint b) { v = v * b.inv().v % mod; return *this; } inline mint operator+(const mint b) const { return mint(v) += b; } inline mint operator-(const mint b) const { return mint(v) -= b; } inline mint operator*(const mint b) const { return mint(v) *= b; } inline mint operator/(const mint b) const { return mint(v) /= b; } friend ostream& operator<<(ostream& os, const mint& m) { return os << m.v; } friend istream& operator>>(istream& is, mint& m) { int x; is >> x; m = mint(x); return is; } bool operator<(const mint& r)const { return v < r.v; } bool operator>(const mint& r)const { return v > r.v; } bool operator<=(const mint& r)const { return v <= r.v; } bool operator>=(const mint& r)const { return v >= r.v; } bool operator==(const mint& r)const { return v == r.v; } bool operator!=(const mint& r)const { return v != r.v; } explicit operator bool()const { return v; } explicit operator int()const { return v; } mint comb(mint k) { if (k > * this) return mint(); if (!fact[0]) combinit(); if (v >= fn_) { if (k > * this - k) k = *this - k; mint tmp(1); for (int i = v; i >= v - k.v + 1; i--) tmp *= mint(i); return tmp * comp[k.v]; } return fact[v] * comp[k.v] * comp[v - k.v]; }//nCk mint perm(mint k) { if (k > * this) return mint(); if (!fact[0]) combinit(); if (v >= fn_) { mint tmp(1); for (int i = v; i >= v - k.v + 1; i--) tmp *= mint(i); return tmp; } return fact[v] * comp[v - k.v]; }//nPk static void combinit() { fact[0] = 1; for (int i = 1; i < fn_; i++) fact[i] = fact[i - 1] * mint(i); comp[fn_ - 1] = fact[fn_ - 1].inv(); for (int i = fn_ - 2; i >= 0; i--) comp[i] = comp[i + 1] * mint(i + 1); } }; mint mint::fact[fn_], mint::comp[fn_]; //-------------------------------------------------------------- template class sptable { vectora; vectorlog; vector>table; int n; using F = function; F func; public: sptable() {} sptable(vector& b, F comp) :a(b), n(b.size()), func(comp) { log.resize(n + 1); for (int i = 2; i <= n; i++) log[i] = log[i >> 1] + 1; table.assign(log[n] + 1, vector(n)); for (int i = 0; i < n; i++) table[0][i] = i; for (int k = 1; (1 << k) <= n; k++) { for (int i = 0; i + (1 << k) <= n; i++) { int c = table[k - 1][i]; int d = table[k - 1][i + (1 << (k - 1))]; if (func(a[c], a[d]) == a[c]) table[k][i] = c; else table[k][i] = d; } } } template sptable(const Iterator a, const Iterator b, F comp) { vectorc; for (auto k = a; k != b; k++) { c.push_back(*k); } *this = sptable(c, comp); } //[s,t) int query(int s, int t) { t--; int d = t - s + 1, k = log[d]; if (func(a[table[k][s]], a[table[k][t - (1 << k) + 1]]) == a[table[k][s]]) return table[k][s]; else return table[k][t - (1 << k) + 1]; } T num(int s, int t) { return a[query(s, t)]; } }; class LCA { using H = pair; int n; vectore[300000]; vectorord, depth, id; vectordit; sptable st; void dfs(int x, int p, int d, ll dis) { id[x] = (int)ord.size(); ord.push_back(x); depth[x] = d; dit[x] = dis; for (H v : e[x]) { if (v.first != p) { dfs(v.first, x, d + 1, dis + v.second); ord.push_back(x); } } } public: void init(int size) { n = size + 1; for (int i = 0; i < n; i++) e[i].clear(); ord.clear(); depth.clear(); id.clear(); dit.clear(); depth.resize(n); id.assign(n, -1); } void add_edge(int u, int v) { add_edge(u, v, 1); } void add_edge(int u, int v, ll r) { e[u].push_back(H{ v,r }); e[v].push_back(H{ u,r }); } void build(int root = 0) { dit.resize(n); depth.resize(n); id.resize(n); ord.reserve(2 * n - 1); dfs(root, -1, 0, 0); for (int i = 0; i < n; i++) { if (id[i] < 0) dfs(i, -1, 0, 0); } vectorstvec((int)ord.size()); for (int i = 0; i < (int)ord.size(); i++) { stvec[i] = depth[ord[i]]; } st = sptable(stvec, [](int a, int b) {return min(a, b); }); } int get(int u, int v) { return ord[st.query(min(id[u], id[v]), max(id[u], id[v]) + 1)]; } ll dist(int u, int v) { int l = get(u, v); return dit[u] + dit[v] - 2 * dit[l]; } int operator[](int x) { return depth[x]; } }; class BIT { int size; vectordat; public: BIT() {} BIT(int n) { init(n); } void init(int n) { size = n; dat.clear(); dat.assign(size + 1, 0); } void add(int i, int x) { i++; while (i <= size) { dat[i] += x; i += i & -i; } }//0-indexed void add(int l, int r, int x) { add(l, x); add(r, -x); }//[l,r) int query(int i) { i++; int sum = 0; while (i > 0) { sum += dat[i]; i -= i & -i; } return sum; }//0-indexed int query(int l, int r) { return query(r - 1) - query(l - 1); }//[l,r) };//size, 0-indexed //--------------------------------------------------------------------- int n, k; vi a, b; vece; vecf[200000]; vecshn[200000]; LCA lca; mt19937 rnd(314159); void generate(int mode, int num) { a.clear(); b.clear(); e.clear(); rep(i, 200000) f[i].clear(), shn[i].clear(); if (mode == 0) { cin >> n >> k; rep(i, k) a.pb(read() - 1); rep(i, k) b.pb(read()); rep(i, n - 1) { e.pb(readh(1)); f[e[i].fs].pb(e[i].sc); f[e[i].sc].pb(e[i].fs); } } else { n = rnd() % ll(1e5 - 1) + 2, k = rnd() % (n - 1) + 2; if (num <= 7) { n = n % (num) + 2; k = k % (n - 1) + 2; } else if (num <= 13) { n = n % 100 + 2; k = k % (n - 1) + 2; } else if (num <= 34) { } else if (num <= 37) { n = 99800; k = 99800; } else { n = 100000, k = 100000; } vi tmp; rep(i, n) tmp.pb(i); shuffle(all(tmp), rnd); rep(i, k) { a.pb(tmp[i]); } rep(i, k) { if (num == 9) b.pb(0); else if (num == 38) b.pb((ll)rnd() % ll(2 * 1e9) - 1e9); else if (num == 39) b.pb(1e9); else b.pb((ll)rnd() % ll(2 * 1e3) - 1e3); } rng(i, 1, n) { int t = rnd() % i; if (num == 14) { t = i - 1; } else if (n == 15) { t = 0; } e.pb(H{ i,t }); f[i].pb(t); f[t].pb(i); } } } ll guchoku() { lca.init(n); rep(i, n - 1) lca.add_edge(e[i].fs, e[i].sc); lca.build(0); ll ans = 0; int tmp = a[0]; rep(i, k) { ans += b[i]; tmp = lca.get(a[i], tmp); }//全部 ans += lca[tmp]; vi v = { -inf, ans }; rep(i, k)rng(j, i, k) { //[i,j]を消す if (i == 0 && j == k - 1) continue; int t; ll sum = 0; if (i > 0) t = a[0]; else t = a[j + 1]; rep(r, i) { t = lca.get(t, a[r]); sum += b[r]; } rng(r, j + 1, k) { t = lca.get(t, a[r]); sum += b[r]; } v.pb(lca[t] + sum); } sort(all(v)); if (siz(v) != k * ll(k + 1) / 2 + 1) return -inf; return v[(siz(v) + 1) / 2 - 1]; } ll solve() { //どうしようかね 深い順に見ていけばいいんじゃないかな? //まず右端が存在するものを考え、 //その後左端から辿っていき、区間の値を求めなさーい //条件を満たす個数が、個数以上となる最もちいさな値を求めなさーい lca.init(n); rep(i, n - 1) lca.add_edge(e[i].fs, e[i].sc); rep(i, k) shn[a[i]].pb(i); lca.build(0); ll ttt = 0; rep(i, k) ttt += abs(b[i]); vi pa(n, -1); rep(i, n) { for (int g : f[i]) { if (lca[g] == lca[i] - 1) pa[i] = g; } } //bがコストです。 csum lb(b); ll num = (ll(k * ll(k + 1) / 2 + 1) + 1) / 2;//中央値になるための個数 //個数がこれ以下であれば、セーフ ll ok = ttt + n, ng = -ttt - n, mid; while (ok - ng > 1) { mid = (ok + ng) / 2; auto F = [&](ll num) ->ll { ll sum = 1, r = 0; int t = a[k - 1]; for (int i = k - 1; i >= 0; i--) { t = lca.get(t, a[i]); r += b[i]; if (lca[t] + r <= num) sum++; }//i~n-1までを残して、それ以外を全て消し飛ばす場合 //全部使わない、左からの区間を使わない、全部使うをカウントした //左端を使います。 //左端から1個ずつ上がっていきます。 int pre = -1; int cnt = 0; vecc(k, 0); auto dfs = [&](int x, int p, auto dfs) ->void { for (auto g : shn[x]) c[g] = 1, cnt++; for (auto g : f[x]) { if (g != p && g != pre) dfs(g, x, dfs); } }; //座標圧縮をしておくが吉 vi lf = { 0 }, rg = { 0 }; r = 0; rep(i, k) { r += b[i]; lf.pb(r); } r = 0; for (int i = k - 1; i >= 0; i--) { r += b[i]; rg.pb(r); } crdcomp(lf); crdcomp(rg); BIT left(siz(lf)); //左から見た値がnum-right以下のモノを探索する BIT right(siz(rg));//右から見た値がnum-left以下の者を探索する right.add(getidx(rg, 0), 1); int l = 0; r = k - 1;//[0,l), [r+1, k) for (int cur = a[0]; ~cur; cur = pa[cur]) { dfs(cur, pa[cur], dfs); //全部カバーされている場合は、コストの最大化問題に帰着できないんですよね ひーはー //まず適当な処理をします。 if (cnt == k) { //頂点がここのものは、直前のものより一つでも伸ばせばよくて、 //だから、ここになったら気合を出せばよい。 //途中からここまででの総和が何とか以下、みたいなことをすればよくて right.init(siz(rg)); //希望の地、楽園の跡、値さんです right.add(getidx(rg, 0), 1); for (int i = k - 2; i >= l; i--) { sum += right.query(upper_bound(all(rg), num - lb.a(0, i) - lca[cur]) - rg.begin() - 1); //これ以下の値の数 right.add(getidx(rg, lb.b(i + 1, k)), 1); }//左から+右から+深さ<=num //num-左から-深さ>=右から left.init(siz(lf)); for (int i = 1; i <= r; i++) { sum += left.query(upper_bound(all(lf), num - lb.a(i, k - 1) - lca[cur]) - lf.begin() - 1); if (i - 1 < l)left.add(getidx(lf, lb.a(0, i - 1)), 1); } break; } else { while (c[l]) { sum += right.query(upper_bound(all(rg), num - lb.a(0, l) - lca[cur]) - rg.begin() - 1); left.add(getidx(lf, lb.a(0, l)), 1); l++; } while (c[r]) { sum += left.query(upper_bound(all(lf), num - lb.a(r, k - 1) - lca[cur]) - lf.begin() - 1); right.add(getidx(rg, lb.b(r, k)), 1); r--; } } pre = cur; } return sum; }; if (F(mid) >= num) ok = mid; else ng = mid; } return ok; } void edit(int num) { ofstream ofs("input/" + to_string(num) + ".txt"); ofs << n << " " << k << endl; rep(i, k) ofs << a[i] + 1 << ssp(i, k); rep(i, k) ofs << b[i] << ssp(i, k); rep(i, n - 1) { ofs << e[i].fs + 1 << " " << e[i].sc + 1 << endl; } } signed main() { generate(0, 20); ll ans = solve(); cout << ans << endl; /*rep(i, 40) { generate(1, i + 1); edit(i + 1); /*generate(1, 20); int u = guchoku(); int v = solve(); if (u != v) { cout << n << " " << k << endl; rep(i, k) cout << a[i] << ssp(i, k); rep(i, k) cout << b[i] << ssp(i, k); rep(i, n - 1) cout << e[i].fs << " " << e[i].sc << endl; cout << u << endl; cout << endl; cout << v << endl; return 0; } cout << i << endl; }*/ } /* cout << n << " " << k << " " << q << endl; rep(i, k) cout << a[i]+1 << ssp(i, k); rep(i, n - 1) { cout << e[i].fs+1 << " " << e[i].sc+1 << endl; } rep(i, q) { if (queries[i].xx == 1) { cout << 1 << " " << queries[i].yy+1 << " " << queries[i].zz+1 << endl; } else { cout << 2 << " " << queries[i].yy+1 << endl; } } */