P3345 ZJOI2015 幻想鄉戰略遊戲

2022-05-07 17:42:12 字數 3169 閱讀 5256

傲嬌少女幽香正在玩乙個非常有趣的戰略類遊戲,本來這個遊戲的地圖其實還不算太大,幽香還能管得過來,但是不知道為什麼現在的網遊廠商把遊戲的地圖越做越大,以至於幽香一眼根本看不過來,更別說和別人打仗了。 在打仗之前,幽香現在面臨乙個非常基本的管理問題需要解決。 整個地圖是乙個樹結構,一共有 n 塊空地,這些空地被 n−1 條帶權邊連線起來,使得每兩個點之間有一條唯一的路徑將它們連線起來。

在遊戲中,幽香可能在空地上增加或者減少一些軍隊。同時,幽香可以在乙個空地上放置乙個補給站。 如果補給站在點 u 上,並且空地 v 上有 dv 個單位的軍隊,那麼幽香每天就要花費 dv×dist(u,v) 的金錢來補給這些軍隊。由於幽香需要補給所有的軍隊,因此幽香總共就要花費為 ∑(dv×dist(u,v))(其中1≤v≤n)的代價,dist(u,v) 表示 u 個 v 在樹上的距離(唯一路徑的權和)。 因為遊戲的規定,幽香只能選擇乙個空地作為補給站。在遊戲的過程中,幽香可能會在某些空地上製造一些軍隊,也可能會減少某些空地上的軍隊,進行了這樣的操作以後,出於經濟上的考慮,幽香往往可以移動他的補給站從而省一些錢。但是由於這個遊戲的地圖是在太大了,幽香無法輕易的進行最優的安排,你能幫幫她嗎? 你可以假定一開始所有空地上都沒有軍隊。

第一行兩個數 n 和 q 分別表示樹的點數和幽香操作的個數,其中點從 1 到 n 標號。

接下來 n−1 行,每行三個正整數 a,b,c,表示 a 和 b 之間有一條邊權為 c 的邊。

接下來 q 行,每行兩個數 u,e,表示幽香在點 u 上放了 e 單位個軍隊(如果 e<0,就相當於是幽香在 u 上減少了 ∣e∣ 單位個軍隊,說白了就是 du←du+e)。

資料保證任何時刻每個點上的軍隊數量都是非負的。

對於幽香的每個操作,輸出操作完成以後,每天的最小花費,也即如果幽香選擇最優的補給點進行補給時的花費。

輸入 #1

10 5

1 2 1

2 3 1

2 4 1

1 5 1

2 6 1

2 7 1

5 8 1

7 9 1

1 10 1

3 12 1

8 13 1

4 1

輸出 #1

014

56

對於所有資料,\(1≤c≤10^3,0≤∣e∣≤10^3,1≤n≤10^5,1≤q≤10^5\)

非常神奇的是,對於所有資料,這棵樹上的點的度數都不超過 20。

動態點分治的題。

\(sum_x\):表示\(x\)這顆樹內的\(d\)值之和。

\(dum_x\):表示\(x\)這顆樹內的\(d *dis(x, y)\)值之和。

\(fum_x\):表示\(x\)這顆樹內的\(d *dis(fa[x], y)\)值之和。

(其中\(y\)為\(x\)的子樹內的節點,\(fa[x]\)為\(x\)在點分樹上的父親)

​ 我們可以發現其實可以通過貪心的方法找到最小的\(ans\),我們假設一開始在\(x\),那麼遍歷它所有的兒子\(y\),以\(y\)作為補給點找答案,哪個小就往那裡走。如果所有\(y\)的\(ans\)都大於以\(x\)為補給點的\(ans\),那麼\(x\)就是當前最合適的補給點。

​ 假設現在以\(x\)點為補給點,計算\(ans\)的方法:

​ \(dum[fa[i]] - fum[i]\)是綠色部分的點\(y\)到\(fa[x]\)的\(d * dis(y, fa[x])\)值之和,\((sum[fa[i]] - sum[i]) * dist(fa[i], x)\)是綠色部分的點\(y\)的\(d\)值之和乘上\(dis(fa[x], x)\),所以總體就是綠色部分的所有點到\(x\)的\(d * dis(y, x)\)值之和。

​ 求\(dis(x, y)\)要用\(lca\)來求,求\(lca\)要用倍增的方法,這樣時間複雜度低一點。

#include #define int long long

using namespace std;

inline long long read()

const int n = 5e5 + 5, inf = 1e9;

int n, m, rt, cnt, tot, root, totsize;

int f[n][23], fa[n], vst[n], de[n << 2], dep[n], dis[n], vis[n << 2], lg[n << 1], dfn[n], siz[n], link[n << 1], max_siz[n], head[n];

long long sum[n], dum[n], fum[n];

struct edge e[n << 1];

void add(int x, int y, int z)

void get_root(int x, int fa)

max_siz[x] = max(max_siz[x], totsize - siz[x]);

if(max_siz[root] > max_siz[x]) root = x;

}void build(int x, int fa)

}void dfs_pre(int x, int fa)

}void rmq()

} }int lca(int x, int y)

long long dist(int x, int y)

void change(int x, int _3k)

}long long calc(int x)

long long query()

}

if(x == y) break; x = y;

}return tmp;

}signed main()

max_siz[root] = totsize = n;

get_root(1, 0);

rt = root; build(root, 0);

dfs_pre(1, 0); rmq();

for(int i = 1, x, y;i <= m; i++)

return 0;

}

P3345 ZJOI2015 幻想鄉戰略遊戲

題意 求帶權重心,即求乙個點 u 使得最小化 sum dis u,v times w v 輸出這個最小值。點權帶修,多組詢問。動態點分治。先建出點分樹,以下的父子關係均是建立在點分樹上的。s u 表示子樹 u 的點權和 sfa u 表示子樹 u 對 fa u 的貢獻,即 sum dis v,fa u...

P3345 ZJOI2015 幻想鄉戰略遊戲

傳送門 考慮先隨便找乙個點作為根,然後再慢慢移動根,這樣一步步走到最優的點 設 sum x 表示節點 x 的子樹的軍隊數,len x,y 表示 x,y 之間邊的長度 那麼對於根節點 x 的乙個兒子 v 考慮把兒子搞為根時,代價的改變量 v 的子樹內的軍隊消耗減少,共減少了 sum v cdot le...

洛谷P3345 ZJOI2015 幻想鄉戰略遊戲

題目描述 傲嬌少女幽香正在玩乙個非常有趣的戰略類遊戲,本來這個遊戲的地圖其實還不算太大,幽香還能管得過來,但是不知道為什麼現在的網遊廠商把遊戲的地圖越做越大,以至於幽香一眼根本看不過來,更別說和別人打仗了。在打仗之前,幽香現在面臨乙個非常基本的管理問題需要解決。整個地圖是乙個樹結構,一共有n塊空地,...