传送门1
传送门2
写在前面:
当初洗澡的时候脑补了下这个题,觉得很简单直到看到题面,才发现自己记错了,自此开始不归路
思路:这里的链剖实际上就是求每个操作的路径长度(也可以LCA求),然后我想到了二分答案(最大求最小谁不会啊!)进行判断,也想到求交集了,但是卡在交集这里了,发现好几个问题,比如究竟删掉的边是交最多的还是权值最大的还是另有他法,而且这也用线段树来搞的话会被卡常……想的方法也是实现了好久……
二分总路径长度x,把大于x的操作在线段树上打一下标记并sum++,最后看一下每条边的标记个数,如果标记个数=sum那么这条边是可以删去的(如果删去那些标记个数<sum的边,肯定有长度>x的路径没受到影响),最后判断操作中最长的路径长度-标记=sum的最长边是否小于等于x就可以了,复杂度O(mlog2n)O(mlog^2n)
95分线段树版本

#include<bits/stdc++.h>
#define M 300002
using namespace std;
int in()
{int t=0;char ch=getchar();while (ch>'9'||ch<'0') ch=getchar();while (ch>='0'&&ch<='9') t=t*10+ch-'0',ch=getchar();return t;
}
int ans,n,m,tot,cnt,sum;
int num[M],fa[M],son[M],t[M],siz[M],L[M],pre[M],dep[M],first[M],top[M],tree[M<<2],a[M<<2];
bool flag[M];
struct edge
{int u,v,w,next;
}e[M<<1];
struct os
{int x,y,dis;
}q[M];
void add(int x,int y,int z)
{e[++tot].v=y;e[tot].u=x;e[tot].w=z;e[tot].next=first[x];first[x]=tot;
}
void dfs1(int x)
{siz[x]=1;for (int i=first[x];i;i=e[i].next)if (e[i].v!=fa[x]){dep[e[i].v]=dep[x]+1;fa[e[i].v]=x;dfs1(e[i].v);if (siz[e[i].v]>siz[son[x]]) son[x]=e[i].v;siz[x]+=siz[e[i].v]; }
}
void dfs2(int x,int tp)
{top[x]=tp;L[x]=++cnt;pre[cnt]=x;if (son[x]) dfs2(son[x],tp);for (int i=first[x];i;i=e[i].next)if (e[i].v!=fa[x]&&e[i].v!=son[x]) dfs2(e[i].v,e[i].v);
}
void build(int now,int begin,int end)
{if (begin==end){tree[now]=t[pre[end]];return;}int mid=(begin+end)>>1;build(now<<1,begin,mid);build(now<<1|1,mid+1,end);tree[now]=tree[now<<1]+tree[now<<1|1];
}
int get(int now,int begin,int end,int l,int r)
{if (l<=begin&&end<=r) return tree[now];int mid=(begin+end)>>1,ans=0;if (mid>=l) ans+=get(now<<1,begin,mid,l,r);if (mid<r) ans+=get(now<<1|1,mid+1,end,l,r);return ans;
}
void pushdown(int now,int begin,int end)
{if (!a[now]) return;int mid=(begin+end)>>1;a[now<<1]+=a[now];a[now<<1|1]+=a[now];a[now]=0;
}
void update(int now,int begin,int end,int l,int r,int mk)
{if (l<=begin&&end<=r) {a[now]+=mk;return;}pushdown(now,begin,end);int mid=(begin+end)>>1;if (mid>=l) update(now<<1,begin,mid,l,r,mk);if (mid<r) update(now<<1|1,mid+1,end,l,r,mk);
}
void fills(int x,int y,int mk)
{int f1=top[x],f2=top[y];while (f1!=f2){if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);update(1,1,cnt,L[f1],L[x],mk);x=fa[f1];f1=top[x];}if (dep[x]>dep[y]) swap(x,y);if (x!=y) update(1,1,cnt,L[son[x]],L[y],mk);
}
void down(int now,int begin,int end)
{if (begin==end) {num[pre[end]]=a[now];return;}pushdown(now,begin,end);int mid=(begin+end)>>1;down(now<<1,begin,mid);down(now<<1|1,mid+1,end);
}
bool check(int x)
{int maxn_q=0,maxn_e=0;for (int i=1;i<=m;i++)if (q[i].dis>x){maxn_q=max(maxn_q,q[i].dis);if (!flag[i]) flag[i]=1,sum++,fills(q[i].x,q[i].y,1);}elseif (flag[i]) flag[i]=0,sum--,fills(q[i].x,q[i].y,-1);down(1,1,cnt);//把标记放下来,查询每个线段被覆盖的次数for (int i=1;i<=cnt;i++)if (num[i]==sum) maxn_e=max(maxn_e,t[i]);return maxn_q-maxn_e<=x;
}
main()
{n=in();m=in();int x,y,z,f1,f2;int l=0,r=0;for (int i=1;i<n;i++)x=in(),y=in(),z=in(),add(x,y,z),add(y,x,z);dfs1(1);dfs2(1,1);for (int i=1;i<=tot;i++){if (dep[e[i].v]<dep[e[i].u]) swap(e[i].v,e[i].u);t[e[i].v]=e[i].w;}build(1,1,cnt);for (int i=1;i<=m;i++){scanf("%d%d",&x,&y);q[i].x=x;q[i].y=y;f1=top[x];f2=top[y];while (f1!=f2){if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);q[i].dis+=get(1,1,cnt,L[f1],L[x]);x=fa[f1];f1=top[x];}if (dep[x]>dep[y]) swap(x,y);if (x!=y) q[i].dis+=get(1,1,cnt,L[son[x]],L[y]);r=max(r,q[i].dis);}while (l<=r){int mid=(l+r)>>1;if (check(mid)) ans=mid,r=mid-1;else l=mid+1;}printf("%d",ans);
}

后来又调了好久的差分……还是不太能理解
100分差分版本

#include<bits/stdc++.h>
#define M 300002
using namespace std;
int in()
{int t=0;char ch=getchar();while (ch>'9'||ch<'0') ch=getchar();while (ch>='0'&&ch<='9') t=t*10+ch-'0',ch=getchar();return t;
}
int ans,n,m,tot,cnt;
int t[M],num[M],fa[M],son[M],siz[M],L[M],pre[M],dep[M],first[M],top[M],tree[M<<2];
struct edge
{int u,v,w,next;
}e[M<<1];
struct os
{int x,y,dis;
}q[M];
void add(int x,int y,int z)
{e[++tot].u=x;e[tot].v=y;e[tot].w=z;e[tot].next=first[x];first[x]=tot;
}
void dfs1(int x)
{siz[x]=1;for (int i=first[x];i;i=e[i].next)if (e[i].v!=fa[x]){dep[e[i].v]=dep[x]+1;fa[e[i].v]=x;dfs1(e[i].v);if (siz[e[i].v]>siz[son[x]]) son[x]=e[i].v;siz[x]+=siz[e[i].v]; }
}
void dfs2(int x,int tp)
{top[x]=tp;L[x]=++cnt;pre[cnt]=x;if (son[x]) dfs2(son[x],tp);for (int i=first[x];i;i=e[i].next)if (e[i].v!=fa[x]&&e[i].v!=son[x]) dfs2(e[i].v,e[i].v);
}
void build(int now,int begin,int end)
{if (begin==end){tree[now]=t[pre[end]];return;}int mid=(begin+end)>>1;build(now<<1,begin,mid);build(now<<1|1,mid+1,end);tree[now]=tree[now<<1]+tree[now<<1|1];
}
int get(int now,int begin,int end,int l,int r)
{if (l<=begin&&end<=r) return tree[now];int mid=(begin+end)>>1,ans=0;if (mid>=l) ans+=get(now<<1,begin,mid,l,r);if (mid<r) ans+=get(now<<1|1,mid+1,end,l,r);return ans;
}
bool check(int x)
{memset(num,0,sizeof(num));int sum=0,mp=0,l,r,f1,f2,maxn_q=0,maxn_e=0;for (int i=1;i<=m;i++)if (q[i].dis>x){sum++;maxn_q=max(maxn_q,q[i].dis);l=q[i].x;r=q[i].y;f1=top[l];f2=top[r];while (f2!=f1){if (dep[f1]<dep[f2]) swap(f1,f2),swap(l,r);num[L[f1]]++;num[L[l]+1]--;l=fa[f1];f1=top[l];}if (l==r)continue;if (dep[l]>dep[r]) swap(l,r);num[L[son[l]]]++;num[L[r]+1]--; }for (int i=1;i<=cnt;i++){mp+=num[i];if (mp==sum) maxn_e=max(maxn_e,t[pre[i]]);}return maxn_q-maxn_e<=x;
}
main()
{n=in();m=in();int x,y,z,f1,f2;int l=0,r=0;for (int i=1;i<n;i++)x=in(),y=in(),z=in(),add(x,y,z),add(y,x,z);dfs1(1);dfs2(1,1);for (int i=1;i<=tot;i++){if (dep[e[i].v]<dep[e[i].u]) swap(e[i].v,e[i].u);t[e[i].v]=e[i].w;}build(1,1,cnt);for (int i=1;i<=m;i++){x=in();y=in();q[i].x=x;q[i].y=y;f1=top[x];f2=top[y];while (f1!=f2){if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);q[i].dis+=get(1,1,cnt,L[f1],L[x]);x=fa[f1];f1=top[x];}if (dep[x]>dep[y]) swap(x,y);if (x!=y) q[i].dis+=get(1,1,cnt,L[son[x]],L[y]);r=max(r,q[i].dis);}while (l<=r){int mid=(l+r)>>1;if (check(mid)) ans=mid,r=mid-1;else l=mid+1;}printf("%d",ans);
}

这道题给我的启发还是挺深的。,别人的code是别人思想方法的结晶,即使是偶尔想偷懒地模仿也是不可能成功的,更是白白浪费时间,深入的思考才能真正体会到题目的内涵与解决方法;小细节也是要注意的,而且不要去尝试从code上体会别人的思想,而是自己思考后结合别人的文字思路来加深印象与体会

【codevs4632】【BZOJ4326】运输计划,链剖+二分+差分相关推荐

  1. 洛谷P2680 运输计划(倍增LCA + 树上差分 + 二分答案)

    [题目链接] [思路]: 根据题意可以明显看出,当所有任务都完成时的时间是最终的结果,也就是说本题要求,求出最小的最大值. 那这样的话就暗示了将答案二分,进行check. [check方法]: 如果说 ...

  2. [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告

    [NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...

  3. luogu P2680 运输计划 (二分答案+树上差分)

    题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...

  4. BZOJ 4326 NOIP2015 运输计划(树上差分+LCA+二分答案)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 1388  Solved: 860 [Submit][Stat ...

  5. P2680 运输计划(树上差分+lca+二分)

    题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...

  6. [luogu2680] 运输计划 (lca+二分+树上差分)

    传送门 Description Input Output 一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间. Sample Input 6 3 1 2 3 1 6 4 3 1 7 4 3 ...

  7. 【Bzoj4326】运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 1091  Solved: 696 [Submit][Stat ...

  8. [NOIP2015提高组]运输计划

    题目:BZOJ4326.洛谷P2680.Vijos P1983.UOJ#150.codevs4632.codevs5440. 题目大意:有一棵带权树,有一些运输计划,第i个运输计划从ai到bi,耗时为 ...

  9. cogs2109 [NOIP2015] 运输计划

    cogs2109 [NOIP2015] 运输计划 二分答案+树上差分. STO链剖巨佬们我不会(太虚伪了吧 首先二分一个答案,下界为0,上界为max{路径长度}. 然后判断一个答案是否可行,这里用到树 ...

最新文章

  1. Spring 梳理 - ContentNegotiatingViewResolver
  2. Meet in the middle
  3. java学习笔记15--多线程编程基础2
  4. centos nginx不是命令_虚拟机下Centos 8.0 安装PHP+Mysql+Nginx
  5. mysql临时表好处和坏处_mysql临时表产生的执行效率问题改进(转)
  6. 安卓app与阿里云服务器的无线通信(非局域网)
  7. 19岁中专学历是怎么在广州找到前端工作的?
  8. termux配置python安装kali_安卓安装kali linux之Termux
  9. (39)System Verilog线程停止(disable)
  10. 4.19计算机网络笔记
  11. configure 查找依赖库_由浅入深:Python 中如何实现自动导入缺失的库?
  12. pagerank数据集_机器学习十大经典算法-PageRank(附实践代码)
  13. 网络安全:教你五招服务器安全维护技巧
  14. √【物流网络规划】库存和仓储 warehouse
  15. 在用JAVA写一个简易CAD程序时的笔记
  16. 牛客练习赛53 老瞎眼 pk 小鲜肉[思维+离线+线段树]
  17. java中的java.lang.RuntimeException异常怎么解决?
  18. 2021基于Debian的All in One(NAS+软路由)配置教程
  19. 中科红旗:开源的野心
  20. 核心单词Word List 41

热门文章

  1. Spark内核解析2
  2. Kotlin学习笔记 第二章 类与对象 第十节 内部类嵌套类
  3. Android笔记 fragment的向下兼容
  4. 表达式类型( 一个表达式和一棵二叉树之间,存在着自然的对应关系。写一个程序,实现 基于二叉树表示的算术表达式Expression的操作)
  5. 特征工程系列学习(零)引言
  6. html为什么div移动不了,如何使用Jquery将html从一个div移动到另一个div而不会破坏javascript...
  7. tinypng 批量处理插件_分享六款逆天的Excel插件,高效处理数据必备!低调使用...
  8. RHEL7升级自带Git
  9. Mac上Java开发环境配置
  10. Windows平台下sbt的安装设置