标签:cal change amp this pos private word 游戏 number
#include <cstdio> #include <cstdlib> #define Max 100005 void read (int &now) { now = 0; register char word = getchar (); while (word < ‘0‘ || word > ‘9‘) word = getchar (); while (word >= ‘0‘ && word <= ‘9‘) { now = now * 10 + word - ‘0‘; word = getchar (); } } #define INF 1e60 int Heart; int N, M; long long Total; inline int swap (int &a, int &b) { int now = a; a = b; b = now; } struct S_D { S_D *Left, *Right; int Mid; int key; int l, r; S_D (int __l, int __r) { r = __r; Left = Right = NULL; Mid = __l + __r >> 1; l = __l; key = 0; } inline void Updata () { this->key = this->Left->key + this->Right->key; } }; struct Edge_Data { int to; int next; int value; }; long long Answer; struct Point_Data { int size; int deep; int tree_number; int up; int father; }; inline int min (int a, int b) { return a < b ? a : b; } inline int max (int a, int b) { return a > b ? a : b; } class S_T { private : S_D *Root; void __Build_ (S_D *&now, int l, int r) { now = new S_D (l, r); if (l == r) return ; __Build_ (now->Left, l, now->Mid); __Build_ (now->Right, now->Mid + 1, r); } int __Query_ (S_D *&now, int l, int r) { if (l <= now->l && now->r <= r) return now->key; int res = 0; if (l <= now->Mid) res += __Query_ (now->Left, l, min (now->Mid, r)); if (r > now->Mid) res += __Query_ (now->Right, max (now->Mid + 1, l), r); return res; } void __Change_ (S_D *&now, int pos, int to) { if (now->l == now->r) { now->key += to; return ; } if (pos <= now->Mid) __Change_ (now->Left, pos, to); else __Change_ (now->Right, pos, to); now->Updata (); } public : void Build (int l, int r) { __Build_ (Root, l, r); return ; } int Query (int l, int r) { return __Query_ (Root, l, r); } void Change (int pos, int to) { __Change_ (Root, pos, to); return ; } }; S_T Tree; class T_T { private : int edge_list[Max]; Edge_Data edge[Max << 2]; int Edge_Count; Point_Data point[Max]; inline void Add_Edge (int from, int to, int dis) { Edge_Count ++; edge[Edge_Count].to = to; edge[Edge_Count].next = edge_list[from]; edge[Edge_Count].value = dis; edge_list[from] = Edge_Count; Edge_Count ++; edge[Edge_Count].to = from; edge[Edge_Count].value = dis; edge[Edge_Count].next = edge_list[to]; edge_list[to] = Edge_Count; } int Count; void Dfs_1 (int now, int father) { int pos = Count ++; point[now].father = father; point[now].deep = point[father].deep + 1; for (int i = edge_list[now]; i; i = edge[i].next) if (edge[i].to != father) Dfs_1 (edge[i].to, now); point[now].size = Count - pos; } void Dfs_2 (int now, int chain) { int pos = 0; point[now].up = chain; point[now].tree_number = ++Count; for (int i = edge_list[now]; i; i = edge[i].next) if (!point[edge[i].to].tree_number && point[edge[i].to].size > point[pos].size) pos = edge[i].to; if (!pos) return ; Dfs_2 (pos, chain); for (int i = edge_list[now]; i; i = edge[i].next) if (edge[i].to != pos && !point[edge[i].to].tree_number) Dfs_2 (edge[i].to, edge[i].to); } public : void Insert_edges () { for (int i = 1, x, y, z; i < N; i++) { read (x); read (y); read (z); Add_Edge (x, y, z); } } int Get_Lca (int x, int y) { while (point[x].up != point[y].up) { if (point[point[x].up].deep < point[point[y].up].deep) swap (x, y); x = point[point[x].up].father; } return point[x].deep < point[y].deep ? x : y; } void Prepare () { Count = 0; Dfs_1 (1, 0); Count = 0; Dfs_2 (1, 1); Tree.Build (1, N); } int Get_Dis (int x, int y) { // printf ("\n\n\n%d +__+_+_ %d \n\n\n", point[x].deep, point[y].deep); return point[x].deep + point[y].deep - 2 * point[Get_Lca (x, y)].deep; } long long Calculate (int now, int v) { int now_1, now_2; if (now == point[Heart].father) { now_1 = Tree.Query (point[Heart].tree_number, point[Heart].tree_number + point[Heart].size - 1); now_2 = Total - now_1; } else { now_2 = Tree.Query (point[now].tree_number, point[now].tree_number + point[now].size - 1); now_1 = Total - now_2; } return Answer + (long long) (now_1 - now_2) * v; } void Move_Heart (int now) { long long Minn = (long long)INF, res; int pos = 0; for (int i = edge_list[now]; i; i = edge[i].next) { res = Calculate (edge[i].to, edge[i].value); if (res < Minn) { Minn = now; pos = edge[i].to; } } if (Minn < Answer) { Heart = pos; Answer = Minn; Move_Heart (Heart); } } int Get_tree_number (int x) { return point[x].tree_number; } }; T_T Make; int main (int argc, char *argv[]) { read (N); read (M); int x, y; Make.Insert_edges (); Make.Prepare (); Heart = 1; for (; M --; ) { read (x); read (y); Answer += (long long) y * Make.Get_Dis (x, Heart); // printf ("%d --- ---- ---\n", Make.Get_Dis (x, Heart) ); Total += y; Tree.Change (Make.Get_tree_number (x), y); Make.Move_Heart (Heart); printf ("%lld\n", Answer); } // system ("pause"); return 0; }
标签:cal change amp this pos private word 游戏 number
原文地址:http://www.cnblogs.com/ZlycerQan/p/6959270.html