http://172.20.6.3/Problem_Show.asp?id=1454

从这道题我充分认识到我的脑子里好多水orz。

如果知道了这个要用二分和差分写,就没什么思考上的难点了(屁咧你写了一个下午)。

下面讲述一下我写这道题的辛酸历程:

我最开始写了个树链剖分+线段树+二分+差分数组,tle了一个点,这完全搞不懂啊,什么鬼啊,为什么啊,不然你告诉我怎么写啊。

然后我去找了a了此题的Lcentury大神,然后他告诉我:“这个题要用tarjan求lca啊,都什么年代了还用树链剖分,tanjan快啊,你这肯定要超时的。”然后我就信了Lcentury大神的邪学了一波tanjan。

我还很奇怪,tanjan怎么求两点之间距离啊???等到我辛辛苦苦读了一遍tanjan求两点距离的写法之后,狂喷凌霄血,原来只要找到lca一减就出来了,所以说树链剖分找lca是不会tle的,tle是因为我多加了一个sb线段树。

所以我两种都写了一遍[二哈],事实证明两种方案速度的确没有差很多。。。大数据一个是2609ms一个是2640ms。

下面展示我的两个代码(mdzz),就当mark模板了。

tanjan

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
#define lc x*2
#define rc x*2+1
const int maxn=;
int n,m;
struct nod{
int next,y,v;
}e[maxn*];
int head[maxn]={},tot=;
struct wtf{
int x,y,fa,v;
}a[maxn];
struct node{
int y,id,next;
}d[maxn*];
int lin[maxn]={};
int fa[maxn]={};
int f[maxn]={};
int cnt,ned;
int vis[maxn]={};
int dis[maxn]={};
inline void init(int x,int y,int v){
e[++tot].y=y;
e[tot].v=v;
e[tot].next=head[x];
head[x]=tot;
} inline void insert(int x,int y,int id){
d[++tot].y=y;
d[tot].id=id;
d[tot].next=lin[x];
lin[x]=tot;
}
int read(){
char ch=getchar();int x=,f=;
while(ch>''||ch<''){if(ch=='-')f=-;ch=getchar();}
while(ch<=''&&ch>=''){x*=;x+=ch-'';ch=getchar();}
return x*f;
}
int find(int x){
if(f[x]==-)
return x;
return f[x]=find(f[x]);
}
void merge(int u,int v){
int x=find(u);
int y=find(v);
if(x!=y) f[x]=y;
}
void tarj(int x){
int y,v;
fa[x]=x;
vis[x]=;
for(int i=head[x];i;i=e[i].next){
y=e[i].y;v=e[i].v;
if(vis[y])continue;
dis[y]=dis[x]+v;
tarj(y);
merge(x,y);
fa[find(x)]=x;
}
for(int i=lin[x];i;i=d[i].next){
y=d[i].y;
if(vis[y])
a[d[i].id].fa=fa[find(y)];
}
}
bool mmp(wtf aa,wtf bb){
return aa.v>bb.v;
}
void dfs3(int x,int pa,int val){
int y,v;
for(int i=head[x];i;i=e[i].next){
y=e[i].y;v=e[i].v;
if(y==pa)continue;
dfs3(y,x,v);
vis[x]+=vis[y];
}
// cout<<ned<<vis[x]<<val<<x<<endl;
if(vis[x]==ned)cnt=max(cnt,val);
}
inline bool check(int x){
cnt=;
memset(vis,,sizeof(vis));
for(int i=;i<=m;i++){
if(a[i].v>x){
vis[a[i].x]++;
vis[a[i].y]++;
vis[a[i].fa]-=;
}
else{
ned=i-;
break;
}
if(i==m)ned=m;
}
dfs3(,,);
if(a[].v-cnt<=x)return ;
else return ;
}
inline int doit(){
int l=,r=a[].v;
while(l<r){
int mid=(l+r)/;
if(check(mid))r=mid;
else l=mid+;
}
return l;
}
int main(){
//freopen("wtf.in","r",stdin);
int size=<<;
char *p=(char*)malloc(size)+size;
__asm__("movl %0,%%esp\n"::"r"(p));
n=read();m=read();
int x,y,v;
for(int i=;i<n;i++){
x=read();y=read();v=read();
init(x,y,v);init(y,x,v);
}tot=;
for(int i=;i<=m;i++){
a[i].x=read();a[i].y=read();
insert(a[i].x,a[i].y,i);
insert(a[i].y,a[i].x,i);
}memset(f,-,sizeof(f));
tarj();
for(int i=;i<=m;i++){
a[i].v=dis[a[i].x]+dis[a[i].y]-dis[a[i].fa]*;
}
sort(a+,a++m,mmp);
printf("%d\n",doit());
return ;
}

树链剖分

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
#define lc x*2
#define rc x*2+1
const int maxn=;
int n,m;
struct nod{
int next,y,v;
}e[maxn*];
int head[maxn]={},tot=;
int dep[maxn]={},fa[maxn]={},kid[maxn]={};
int top[maxn]={};
int dis[maxn]={};
inline void init(int x,int y,int v){
e[++tot].y=y;
e[tot].v=v;
e[tot].next=head[x];
head[x]=tot;
}
int dfs(int x,int pa){
int y,val,v,tsn=,hug=;
dep[x]=dep[pa]+;
fa[x]=pa;
for(int i=head[x];i;i=e[i].next){
y=e[i].y;v=e[i].v;
if(y==pa)continue;
dis[y]=dis[x]+v;
val=dfs(y,x);
if(val>hug)hug=val,kid[x]=y;
tsn+=val;
}
tsn+=;
return tsn;
}
void dfs1(int x,int pa){
int y,v;
top[x]=pa;
if(kid[x])dfs1(kid[x],pa);
for(int i=head[x];i;i=e[i].next){
y=e[i].y;v=e[i].v;
if(y==fa[x]||y==kid[x])continue;
dfs1(y,y);
}
}
int getit(int x,int y){
int xx=top[x],yy=top[y];
while(xx!=yy){
if(dep[xx]<dep[yy]){
swap(xx,yy);
swap(x,y);
}
x=fa[xx];xx=top[x];
}
if(dep[x]>dep[y])return y;
return x;
}
int read(){
char ch=getchar();int x=,f=;
while(ch>''||ch<''){if(ch=='-')f=-;ch=getchar();}
while(ch<=''&&ch>=''){x*=;x+=ch-'';ch=getchar();}
return x*f;
}
struct wtf{
int x,y,fa,v;
}a[maxn];
bool mmp(wtf aa,wtf bb){
return aa.v>bb.v;
}
int cnt,ned;
int vis[maxn]={};
void dfs3(int x,int val){
int y,v;
for(int i=head[x];i;i=e[i].next){
y=e[i].y;v=e[i].v;
if(y==fa[x])continue;
dfs3(y,v);
vis[x]+=vis[y];
}
if(vis[x]==ned)cnt=max(cnt,val);
}
inline bool check(int x){
cnt=;
memset(vis,,sizeof(vis));
for(int i=;i<=m;i++){
if(a[i].v>x){
vis[a[i].x]++;
vis[a[i].y]++;
vis[a[i].fa]-=;
}
else{
ned=i-;
break;
}
if(i==m)ned=m;
}
dfs3(,);
if(a[].v-cnt<=x)return ;
else return ;
}
inline int doit(){
int l=,r=a[].v;
while(l<r){
int mid=(l+r)/;
if(check(mid))r=mid;
else l=mid+;
}
return l;
}
int main(){
//freopen("wtf.in","r",stdin);
int size=<<;
char *p=(char*)malloc(size)+size;
__asm__("movl %0,%%esp\n"::"r"(p));
n=read();m=read();
int x,y,v;
for(int i=;i<n;i++){
x=read();y=read();v=read();
init(x,y,v);init(y,x,v);
}dfs(,);
dfs1(,);
for(int i=;i<=m;i++){
a[i].x=read();a[i].y=read();
a[i].fa=getit(a[i].x,a[i].y);
a[i].v=dis[a[i].x]+dis[a[i].y]-*dis[a[i].fa];
}sort(a+,a++m,mmp);
printf("%d\n",doit());
return ;
}

JZYZOJ1454 NOIP2015 D2T3_运输计划 二分 差分数组 lca tarjan 树链剖分的更多相关文章

  1. loj2425 「NOIP2015」运输计划[二分答案+树上差分]

    看到题意最小化最长路径,显然二分答案,枚举链长度不超过$\text{mid}$,然后尝试检验.````` 检验是否存在这样一个边置为0后,全部链长$\le\text{mid}$,其最终目标就是.要让所 ...

  2. 【洛谷 P4211】[LNOI2014]LCA(树链剖分,差分)

    题目链接 看到题目肯定首先想到要求LCA(其实是我菜),可乍一看,n与q的规模为5W, 求LCA的复杂度为\(O(logN)\),那么总时间复杂度为\(O(nq\ log\ n)\). 怎么搞呢? 会 ...

  3. [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】

    题目链接: BZOJ - 3626 题目分析 考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就 ...

  4. HDU 5044 (树链剖分+树状数组+点/边改查)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变 ...

  5. BZOJ_4326_[NOIP2015]_运输计划_(二分+LCA_树链剖分/Tarjan+差分)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=4326 给出一棵带有边权的树,以及一系列任务,任务是从树上的u点走到v点,代价为u到v路径上的权 ...

  6. Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)

    Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...

  7. NOIP2015 运输计划 - 二分 + 树链剖分 / (倍增 + 差分)

    BZOJ CodeVS Uoj 题目大意: 给一个n个点的边带权树,给定m条链,你可以选择树中的任意一条边,将它置为0,使得最长的链长最短. 题目分析: 最小化最大值,二分. 二分最短长度mid,将图 ...

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

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

  9. 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)

    P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...

随机推荐

  1. javascript继承机制 & call apply使用说明

    一.继承机制 1.对象冒充:构造函数使用 this 关键字给所有属性和方法赋值,可使 ClassA 构造函数成为 ClassB 的方法,然后调用它. function ClassZ() { this. ...

  2. fundamentals of the jQuery library

    1.why is jquery Only 32kB minified and gzipped. Can also be included as an AMD module Supports CSS3 ...

  3. typeof的用法

    typeof可以返回变量的类型,返回值为字符串,其值有 "undefined" "boolean" "string" "numbe ...

  4. ubuntu 提速

    linux的各大发行版,都有些不必要的服务被默认开启了,针对ubuntu,我们可以采用选择性关闭的方法加速起动,提高系统性能. 这里我们安装一个软件: sudo apt-get install sys ...

  5. sicily 1012. Stacking Cylinders & 1206. Stacking Cylinders

    Time Limit: 1sec    Memory Limit:32MB  Description Cylinders (e.g. oil drums) (of radius 1 foot) are ...

  6. [bugfix]copy属性参数将NSMutableArray变为NSArray类型

    问题:NSMutableArray 声明为 copy 属性参数后即使接受NSMutableArray变量依然为NSArray变量 测试: 属性申明为: 1 @property (nonatomic, ...

  7. dos命令连接mysql并且查看编码方式

    打开cmd: 输入:mysql -hlocalhost -uroot -p 然后: show variables like 'char%';

  8. NFS+inotify实时同步

    Inotify简介 Inotify是一种文件系统事件通告机制,能够实时监控文件系统下文件的访问.修改.删除等各种变化情况并将其作为事件通告给用户态应用程序.Linux内核从2.6.13版本后已经集成了 ...

  9. Leetcode 之Balanced Binary Tree(49)

    用递归的方式来做,左右两棵子树的高度差不超过1.分成两部分,一部分递归得到树的高度,一部分递归检查左右子树是否是平衡二叉树. int getHeight(TreeNode *root) { ; ; } ...

  10. php设计模式六----桥接模式

    1.简介 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦. 这种模式涉及到一个作为桥接 ...