タイトル説明
フレグランスふざけ女の子は非常に興味深い戦略ゲームをプレイしている、このゲームは、パイプの香りが通り抜けることができ、本当にあまりないマップのだろうが、オンラインベンダーのゲームはに、どんどん大きくをマッピングなぜ私は知りません香りは、単に見ているように、しかし、一人で他の人が戦ってみましょう。
戦争の前に、今、非常に基本的な管理の問題に直面した香りが対処する必要があります。全体マップは、これら2点を結ぶそれぞれの間に一意の経路が存在するように、木、オープンスペースは、ストリップを接続する右のN-1側であるN開放領域の合計です。
ゲームでは、香りが地面に軍の数を増加または減少させることができます。一方、香りがデポスペース上に配置することができます。点U上のステージングポストは、軍のオープンスペースDVのVユニットが存在する場合、香りはこれらの力を供給するために、毎日DV * DIST(U、V)のお金を費やす必要があります。
力の香りのニーズのすべてのための香りシグマ(DV * DIST(u、v)は、1 <= V <= N)コストの合計を要するであろう、したがって補充、そしてします。DIST(u、v)は距離ツリーにおけるU番目(右および一意のパス)Vを表します。
ゲームの規定なので、香りがステージングポストとして一つだけのオープンスペースを選択することができます。ゲームの過程で、香りは、いくつかのオープンスペースでいくつかの部隊を作成することができ、また軍隊にオープンスペースの一部を減らすことができる経済的考慮によるもので、将来的にこのような操作を行って、香りは、多くの場合、彼の供給を移動することができます駅は、このようにいくつかのお金を節約します。
しかし、ゲームマップが大きすぎると、香りは簡単に最適配置することができないため、あなたは彼女を助けることができますか?あなたは軍がすべてのオープンスペースに起動しなかったと仮定することができます。
入力形式
最初の2つの数の行nおよびQは請求項1からN個の基準点に、ツリーポイントと操作香りの数を表します。次に、N-1行、各行3つの正の整数、B、C、AとBはCの右側の間のエッジがあることを示します。E | |二つの数字U、Eの次のQラインは、eは軍事U点(E <0、Uの香りを減らすのと同等の場合に香りユニットプットを表し、軍事ユニットを、白は言いますそれは)デュ←デュ+ Eです。軍の数に関するデータの任意の時間は、各点が非負であることを保証します。
出力フォーマット
各動作のために、出力動作が完了した後、日の香り、当たり最小のコスト、すなわち、香り、それが補充最適供給点を選択するために時間がかかる場合。
内蔵点線の木、我々は重力の父親の中心部内のすべてのルールは、のレベルにフォーカスに設定されているが点在しました
ただ、ルートノード(ツリー全体の重心)からの各クエリは、才能のある息子が対応するサブツリー散歩の重心に出て行けば、その(元木)息子よく見えるようになりました
そして、唯一の自分の祖先修正ツリーに行に点在変更を検討
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
typedef long long LL;
template<typename T>inline void read(T &num) {
char ch; int flg = 1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
num*=flg;
}
const int MAXN = 100005;
int n, q, fir[MAXN], cnt;
struct edge { int to, nxt, w; }e[MAXN<<1];
inline void add(int u, int v, int wt) {
e[cnt] = (edge){ v, fir[u], wt }, fir[u] = cnt++;
e[cnt] = (edge){ u, fir[v], wt }, fir[v] = cnt++;
}
int dis[MAXN], son[MAXN], sz[MAXN], top[MAXN], fa[MAXN], dep[MAXN];
inline void dfs(int u, int ff) {
dep[u] = dep[fa[u]=ff] + (sz[u]=1);
for(int i = fir[u], v; ~i; i = e[i].nxt)
if((v=e[i].to) != ff) {
dis[v] = dis[u] + e[i].w;
dfs(v, u), sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
}
inline void dfs2(int u,int tp){
top[u]=tp;
if(son[u])dfs2(son[u],tp);
for(int i = fir[u], v; ~i; i = e[i].nxt)
if((v=e[i].to) != fa[u] && v != son[u])
dfs2(v,v);
}
inline int lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
inline int dist(int u,int v){
return dis[u]+dis[v]-2*dis[lca(u,v)];
}
int Fa[MAXN],size[MAXN],Size,Minr,root,info[MAXN],CNT;
struct EDGE { int to, nxt, rt; }E[MAXN];
inline void ADD(int u,int v,int rr){
E[CNT]=(EDGE){v,info[u],rr},info[u]=CNT++;
}
bool vis[MAXN];
void Getrt(int u, int ff) {
size[u] = 1;
int ret = 0;
for(int i = fir[u], v; ~i; i = e[i].nxt)
if((v=e[i].to) != ff && !vis[v]) {
Getrt(v, u), size[u] += size[v];
ret = max(ret, size[v]);
}
ret = max(ret, Size-size[u]);
if(ret < Minr) Minr = ret, root = u;
}
inline void DFS(int u,int ff){
vis[u]=1; Fa[u]=ff;
for(int i = fir[u], v; ~i; i = e[i].nxt)
if(!vis[v=e[i].to]) {
Minr = n; Size = size[v];
Getrt(v, u);
ADD(u, v, root);
DFS(root, u);
}
}
LL sum[MAXN],sumd[MAXN],sumf[MAXN];
inline void Modify(int u,int val){
sum[u]+=val;
for(int i = u; Fa[i]; i = Fa[i]) {
int len = dist(u, Fa[i]);
sum[Fa[i]] += val;
sumd[Fa[i]] +=val * len;
sumf[i] +=val * len;
}
}
inline LL Count(int u){
LL res=sumd[u];
for(int i=u;Fa[i];i=Fa[i]){
int len=dist(u,Fa[i]);
res+=(sum[Fa[i]]-sum[i])*len;
res+=(sumd[Fa[i]]-sumf[i]);
}
return res;
}
inline LL Query(int u) {
LL tmp = Count(u);
for(int i = info[u]; ~i; i = E[i].nxt)
if(Count(E[i].to) < tmp) return Query(E[i].rt);
return tmp;
}
signed main(){
memset(fir, -1, sizeof fir); memset(info, -1, sizeof info);
read(n), read(q);
for(int i = 1, x, y, z; i < n; ++i) read(x), read(y), read(z), add(x, y, z);
dfs(1, 0), dfs2(1, 1);
Size = Minr = n; Getrt(1, 0);
int RT = root;
DFS(root, 0);
int x, y;
while(q--) {
read(x), read(y);
Modify(x, y);
printf("%lld\n", Query(RT));
}
}