第十二周 11.16---11.22

新的一周>_<

---------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 方便些

  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 }
View Code

 

转载于:https://www.cnblogs.com/wuyuewoniu/p/4970325.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值