JZYZOJ1454 NOIP2015 D2T3_运输计划 二分 差分数组 lca tarjan 树链剖分
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 树链剖分的更多相关文章
- loj2425 「NOIP2015」运输计划[二分答案+树上差分]
		
看到题意最小化最长路径,显然二分答案,枚举链长度不超过$\text{mid}$,然后尝试检验.````` 检验是否存在这样一个边置为0后,全部链长$\le\text{mid}$,其最终目标就是.要让所 ...
 - 【洛谷 P4211】[LNOI2014]LCA(树链剖分,差分)
		
题目链接 看到题目肯定首先想到要求LCA(其实是我菜),可乍一看,n与q的规模为5W, 求LCA的复杂度为\(O(logN)\),那么总时间复杂度为\(O(nq\ log\ n)\). 怎么搞呢? 会 ...
 - [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】
		
题目链接: BZOJ - 3626 题目分析 考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就 ...
 - HDU 5044 (树链剖分+树状数组+点/边改查)
		
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变 ...
 - BZOJ_4326_[NOIP2015]_运输计划_(二分+LCA_树链剖分/Tarjan+差分)
		
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=4326 给出一棵带有边权的树,以及一系列任务,任务是从树上的u点走到v点,代价为u到v路径上的权 ...
 - Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)
		
Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...
 - NOIP2015 运输计划 - 二分 + 树链剖分 / (倍增 + 差分)
		
BZOJ CodeVS Uoj 题目大意: 给一个n个点的边带权树,给定m条链,你可以选择树中的任意一条边,将它置为0,使得最长的链长最短. 题目分析: 最小化最大值,二分. 二分最短长度mid,将图 ...
 - luogu P2680 运输计划 (二分答案+树上差分)
		
题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...
 - 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)
		
P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...
 
随机推荐
- WP8.1 Windows Phone 8.1开发:何如定义Pivot头部样式、定义Pivot头部颜色
			
Windows Phone 8.1 ,如何自定义Pivot头部样式?用Pivot控件完成这样的效果. 网上找了好久,只找到了windows phone 8的解决方案. 终于一个大神给支了招,我觉得我有 ...
 - ”未能加载文件或程序集“Oracle.DataAccess”或它的某一个依赖项
			
引用:http://www.cnblogs.com/joey0210/archive/2012/09/29/2708420.html 上一篇文章说到了DLL引用问题,主要是说的程序中如果使用过了反射, ...
 - telnet如何保存输出内容到本地
			
telnet如何保存输出内容到本地 http://bbs.csdn.net/topics/391023327 一种将程序的标准输出重定向到telnet终端的方法 http://blog.chinaun ...
 - mongodb 学习笔记--- 基础知识
			
1.mongodb的安装 (1) mac使用brew 安装就好 brew install mongodb (2) mkdir /data/db 作为mongodb默认的数据目录 并 sudo chow ...
 - 封装构造函数,用canvas写饼状图和柱状图
			
封装构造函数,用canvas写饼状图和柱状图 封装函数 // 场景 function XDLScence( options ) { this.stage = options.stage; //执行场景 ...
 - vim的各种tips
			
centos系统,修改vim的配置文件 /etc/vimrc 添加如下内容: 1) 打开 vimrc ,添加以下语句来使得语法高亮显示: syntax on 2) 如果此时语法还是没有高亮显示,那么在 ...
 - Linux 各个版本之间的差别
			
一直没有搞清楚RHEL,CentOS,,还有Ubuntu,fedora这些版本之间的差别,搜了一下,整理到这里,备忘吧. 我最关心的: 1, CentOS是在RHEL基础上的免费版: 2, Ubunt ...
 - vue 文件引入
			
直接 <script> 引入 直接下载并用 <script> 标签引入,Vue 会被注册为一个全局变量.重要提示:在开发时请用开发版本,遇到常见错误它会给出友好的警告. 开发环 ...
 - HIbernate学习笔记3 之 缓存和 对象的三种状态
			
一.hibernate一级缓存 * hibernate创建每个Session对象时,都会给该Session分配一块独立的缓冲区,用于存放Session查询出来的对象,这个分配给session的缓存区 ...
 - django渲染模板时跟vue使用的{{ }}冲突解决方法
			
var vm = new Vue({ el: '#app', // 分割符: 修改vue中显示数据的语法, 防止与django冲突 delimiters: ['[[', ']]'], data: { ...