Description:
神樹大人種了一棵有邊權的樹,由於這是神樹大人種的樹,所以這棵樹被命名爲神
神樹。神神樹的邊權爲正. 整. 數. 。神樹大人命令龔詩鋒從 1 號點開始走一個路徑並最終
回到1 號點,且這條路徑經過了所有的邊。一條路徑的代價就是它經過的邊的邊權之
和。龔詩鋒可以加若干條額外邊,第 i 條加的額外邊的邊權爲正. 整. 數. Ai。注. 意. ,龔. 詩. 鋒.
不. 一. 定. 要. 經. 過. 所. 有. 的. 額. 外. 邊. 。
由於龔詩鋒喜歡最最痛,所以對於所有的K ∈[0;m],你需要輸出允許加<= K 條額
外邊的最小路徑代價。
1<=n<=1e5,5s
題解:
不難想到假設求出了表示條不相交路徑的最大長度和,那麼對一個K,就需要求出l,使的最小值
當然這個可以暴力用個平衡樹(離線線段樹)二分。
注意到是個凸函數,然後前l小的和也是個凸函數,且隨着K的增大,l只會右移,所以可以用兩個multiset維護,一個存選了的l條邊,另一個存沒選的,細節比較簡單不講了。
那麼問題在於求f,可以暴力對拍,複雜度
然後這個東西是優化不了的,考慮一個貪心,每次選直徑,把直徑邊權取反,繼續找直徑。
顯然我是不會證明這個東西的正確性的,但是至少能找到i條不相交的路徑。
那麼這個東西顯然可以用ddp優化,update細節有點多,還需要用一個multiset維護一個點的虛兒子的最小和次小,access要改改寫法。
重載一堆東西以後還是可以寫的hhh
複雜度,常數巨大
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
int by;
const int N = 2e5 + 5;
int n, m, x, y, z, w[N];
int v[N];
struct P {
int x, y; ll z;
P(){}
P(int _x, int _y, ll _z) { x = _x, y = _y, z = _z;}
};
bool operator <(P a, P b) {
if(a.z < b.z) return 1;
if(a.z > b.z) return 0;
if(a.x < b.x) return 1;
if(a.x > b.x) return 0;
return a.y < b.y;
}
P operator +(P a, P b) { return P(!a.x ? b.x : a.x, !b.y ? a.y : b.y, a.z + b.z);}
P fan(P a) { swap(a.x, a.y); return a;}
struct nod {
P f1, f2, g, v;
};
nod a[N][2][2];
multiset<P> s[N], g[N];
int fa[N], t[N][2], rev[N], rf[N], dd[N], pf[N];
#define i0 t[i][0]
#define i1 t[i][1]
P calc1(multiset<P> &s) {
if(!s.size()) return P(0, 0, 0);
return *s.rbegin();
}
P calc2(multiset<P> &s) {
if(s.size() < 2) return P(0, 0, 0);
return (*++s.rbegin());
}
template<class T> void cmax(T &a, T b) {if(a < b) a = b;}
void upd(int i, multiset<P> &s, multiset<P> &g, int V, nod &a, nod b, nod c) {
P w = P(i, i, V);
a.f1 = b.f1; cmax(a.f1, b.v + w + c.f1); cmax(a.f1, b.v + w + calc1(s));
a.f2 = c.f2; cmax(a.f2, b.f2 + w + c.v); cmax(a.f2, fan(calc1(s)) + w + c.v);
a.g = max(b.g, c.g);
if(g.size()) cmax(a.g, *g.rbegin());
cmax(a.g, b.f2 + w + c.f1);
cmax(a.g, fan(calc1(s)) + w + calc2(s));
cmax(a.g, b.f2 + w + calc1(s));
cmax(a.g, fan(calc1(s)) + w + c.f1);
a.v = b.v + w + c.v;
}
void upd(int i) {
upd(i, s[i], g[i], v[i], a[i][0][0], a[i0][0][0], a[i1][0][0]);
upd(i, s[i], g[i], v[i], a[i][1][0], a[i1][1][0], a[i0][1][0]);
upd(i, s[i], g[i], -v[i], a[i][0][1], a[i0][0][1], a[i1][0][1]);
upd(i, s[i], g[i], -v[i], a[i][1][1], a[i1][1][1], a[i0][1][1]);
}
void fan(int i) {
if(i) {
swap(i0, i1);
swap(a[i][0][0], a[i][1][0]);
swap(a[i][0][1], a[i][1][1]);
rev[i] ^= 1;
}
}
void fu(int i) {
if(i) {
v[i] = -v[i];
swap(a[i][0][0], a[i][0][1]);
swap(a[i][1][0], a[i][1][1]);
rf[i] ^= 1;
}
}
void down(int i) {
if(rev[i]) fan(i0), fan(i1), rev[i] = 0;
if(rf[i]) fu(i0), fu(i1), rf[i] = 0;
}
void xc(int x) {
for(; x; x = fa[x]) dd[++ dd[0]] = x;
while(dd[0]) down(dd[dd[0] --]);
}
int lr(int x) { return t[fa[x]][1] == x;}
void rotate(int x) {
int y = fa[x], k = lr(x);
t[y][k] = t[x][!k]; if(t[x][!k]) fa[t[x][!k]] = y;
fa[x] = fa[y]; if(fa[y]) t[fa[y]][lr(y)] = x;
fa[y] = x; t[x][!k] = y; pf[x] = pf[y];
upd(y); upd(x);
}
void splay(int x, int y) {
xc(x);
for(; fa[x] != y; rotate(x))
if(fa[fa[x]] != y) rotate(lr(x) == lr(fa[x]) ? fa[x] : x);
}
void access(int x) {
int xx = x;
for(int y = 0; x; ) {
splay(x, 0);
if(y) {
s[x].erase(s[x].find(a[y][0][0].f1));
g[x].erase(g[x].find(a[y][0][0].g));
}
y = x, x = pf[x];
}
x = xx;
for(int y = 0; x; ) {
splay(x, 0); fa[t[x][1]] = 0, pf[t[x][1]] = x;
if(t[x][1]) {
s[x].insert(a[t[x][1]][0][0].f1);
g[x].insert(a[t[x][1]][0][0].g);
}
t[x][1] = y, fa[y] = x, pf[y] = 0;
y = x, upd(x), x = pf[x];
}
}
void mr(int x) {
access(x); splay(x, 0);
fan(x);
}
void link(int x, int y) {
mr(x); mr(y);
pf[x] = y;
s[y].insert(a[x][0][0].f1);
g[y].insert(a[x][0][0].g);
access(x);
}
ll f[N];
ll sum, ans;
multiset<int> s1, s2;
int main() {
freopen("love.in", "r", stdin);
freopen("love.out", "w", stdout);
scanf("%d %d", &n, &m);
fo(i, 1, n - 1) {
scanf("%d %d %d", &x, &y, &z);
ans += z * 2;
v[n + i] = z;
link(x, n + i); link(n + i, y);
}
fo(i, 1, n) {
mr(1);
P p = a[1][0][0].g;
f[i] = f[i - 1];
if(p.z >= 0) {
f[i] += p.z;
mr(p.x); access(p.y); splay(p.y, 0);
fu(p.y);
}
}
pp("%lld ", ans);
int l = 0;
fo(i, 1, m) {
scanf("%d", &w[i]);
if(s1.size() && (*s1.rbegin()) > w[i]) {
sum += w[i] - (*s1.rbegin());
s2.insert(*s1.rbegin());
s1.erase(s1.find(*s1.rbegin()));
s1.insert(w[i]);
} else s2.insert(w[i]);
while(s2.size() && (sum + *s2.begin()) - f[l + 1] <= sum - f[l]) {
sum += *s2.begin();
s1.insert(*s2.begin());
s2.erase(s2.begin());
l ++;
}
pp("%lld ", ans + sum - f[l]);
}
}