新的一周>_<
---------11.16
补题--
越来越觉得笨得可以了--
----------11.17
补了南阳最短路那题
那样的转化还是不是很懂---
---- wo shi sb----
---------11.18
补了南阳的 修乒乓器室,台球室那题dp
全程看题解---还是觉得理解得好艰难啊--
---------11.19
补了多校第一场的一道题
hdu 5296
给出一棵树,然后有2个操作
1 x 是将 x 节点 加入 集合 中
2 x 是将 x 节点从集合中删除
为了使集合中的任意两个点都是联通的,至少需要加的边权
-----没有思路-----------------
看的题解了
假设一条链的两端 是 x 和 y ,一个节点 u
u 到 链 x---y 的距离大概是这样来算的
u 到 x 端的距离 dis[u] + dis[x] - 2dis[Lca(x,u)]
u 到 y 端的距离 dis[u] + dis[y] - 2dis[Lca(y,u)]
多算了 x 到 y 的距离 dis[x] + dis[y] - 2dis[Lca(x,y)]
所以 u 到 链 x --- y 的距离为
{ dis[u] + dis[x] - 2dis[Lca(x,u)] + dis[u] + dis[y] - 2dis[Lca(y,u)] - dis[x] + dis[y] - 2dis[Lca(x,y)]}/2
然后,就是x,y端的选择
题解说根据 dfn 来选
选择节点 u 左边和右边挨得最近 的 x ,y
如果没找到的话,就分别是 最小的,最大的
可是为什么是这样,,,,
画了几下,貌似这样的距离是更小的,,,,
自己先用的set的lower_bound 和 upper_bound来找 左右两边的
可是写搓了
后来看了别人的代码
发现是漏了 在 添加操作的时候,那个节点本来就在集合里面
在删除的时候,那个节点本来就不在集合里面
这两种情况
然后,,还学到了 set的重载,从大到小的放元素,直接找不到就是 到 了 set.end()
感觉比自己这样一边找到 begin(),一边找到 end 方便些
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<set> 6 #include<vector> 7 using namespace std; 8 9 typedef long long LL; 10 const int MAXN = 4e5+5; 11 const int MAX_LOG = 32; 12 int n,q,ecnt,tot; 13 int first[MAXN],dfn[MAXN],ddfn[MAXN]; 14 int fa[MAX_LOG][MAXN],dep[MAXN]; 15 int dis[MAXN]; 16 17 struct Edge{ 18 int u,v,nxt,w; 19 }e[MAXN]; 20 21 void init(){ 22 memset(first,-1,sizeof(first)); 23 ecnt = tot = 0; 24 } 25 26 void Add_edge(int u,int v,int w){ 27 e[ecnt].u = u; 28 e[ecnt].v = v; 29 e[ecnt].w = w; 30 e[ecnt].nxt = first[u]; 31 first[u] = ecnt++; 32 } 33 34 void Dfs(int p,int pre,int d){ 35 dfn[p] = ++tot; 36 ddfn[tot] = p; 37 dep[p] = d; 38 fa[0][p] = pre; 39 for(int i = first[p];~i;i = e[i].nxt){ 40 int v = e[i].v; 41 if(v == pre) continue; 42 dis[v] = dis[p] + e[i].w; 43 Dfs(v,p,d+1); 44 } 45 } 46 47 void Pre(){ 48 dis[1] = 0; 49 Dfs(1,-1,0); 50 for(int k = 0;k+1 < MAX_LOG;++k){ 51 for(int v = 1;v <= n;++v){ 52 if(fa[k][v] < 0) fa[k+1][v] = -1; 53 else fa[k+1][v] = fa[k][fa[k][v]]; 54 } 55 } 56 } 57 58 int Lca(int u,int v){ 59 if(dep[u] > dep[v]) swap(u,v); 60 for(int k = MAX_LOG-1;k >= 0;--k){ 61 if((dep[v]-dep[u]) & (1<<k)) v = fa[k][v]; 62 } 63 if(u == v) return u; 64 for(int k = MAX_LOG-1;k >= 0;--k){ 65 if(fa[k][u] != fa[k][v]){ 66 u = fa[k][u]; 67 v = fa[k][v]; 68 } 69 } 70 return fa[0][u]; 71 } 72 73 void solve(){ 74 set<int> s; 75 set<int>::iterator l,it,r,itt; 76 77 int ans = 0,x,y; 78 for(int i = 1;i <= q;i++){ 79 int cmd,u; 80 scanf("%d %d",&cmd,&u); 81 if(cmd == 1){ 82 if(s.size() == 0){ 83 puts("0"); 84 s.insert(dfn[u]); 85 continue; 86 } 87 if(s.find(dfn[u]) != s.end()){ 88 printf("%d\n",ans); 89 s.insert(dfn[u]); 90 continue; 91 } 92 l = s.lower_bound(dfn[u]); 93 r = s.upper_bound(dfn[u]); 94 if(l == s.begin() || r == s.end()){ 95 l = s.begin();r = s.end();r--; 96 } 97 else l--; 98 x = ddfn[*l];y = ddfn[*r]; 99 // printf("x = %d y = %d\n",x,y); 100 ans += dis[u] - dis[Lca(x,u)] - dis[Lca(u,y)] + dis[Lca(x,y)]; 101 printf("%d\n",ans); 102 s.insert(dfn[u]); 103 } 104 else{ 105 if(s.find(dfn[u]) == s.end()){ 106 printf("%d\n",ans); 107 continue; 108 } 109 s.erase(dfn[u]); 110 if(s.size() == 0){ 111 puts("0"); 112 continue; 113 } 114 l = s.lower_bound(dfn[u]); 115 r = s.upper_bound(dfn[u]); 116 if(l == s.begin() || r == s.end()){ 117 l = s.begin();r = s.end();r--; 118 } 119 else l--; 120 x = ddfn[*l];y = ddfn[*r]; 121 ans -= dis[u] - dis[Lca(x,u)] - dis[Lca(u,y)] + dis[Lca(x,y)]; 122 printf("%d\n",ans); 123 } 124 } 125 } 126 127 int main(){ 128 int T; 129 scanf("%d",&T); 130 int kase = 0; 131 while(T--){ 132 init(); 133 scanf("%d %d",&n,&q); 134 for(int i = 1;i <= n-1;i++){ 135 int u,v,w; 136 scanf("%d %d %d",&u,&v,&w); 137 Add_edge(u,v,w); 138 Add_edge(v,u,w); 139 } 140 Pre(); 141 printf("Case #%d:\n",++kase); 142 solve(); 143 } 144 return 0; 145 }