luogu2542 航线规划 (树链剖分)
不会lct,所以只能树剖乱搞
一般这种删边的题都是离线倒着做,变成加边
他要求的结果其实就是缩点以后两点间的距离。
然后先根据最后剩下的边随便做出一个生成树,然后假装把剩下的边当成加边操作以后处理
这样的话,就可以做树剖来维护现在的两点间距离。
然后考虑加边,其实就是加了一条边然后某一处成环了,缩成了一个点。
这样的话,就可以把这条边两个端点间的距离都改成0,假装缩了点。
最后再倒着输出答案就行了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#define inf 0x3f3f3f3f
#define LL long long int
using namespace std;
const int maxn=,maxm=,maxq=; inline LL rd(){
LL x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Edge{
int a,b,ne;bool used,flag;
}eg[maxm*];
int N,M;
int egh[maxn],ect;
int que[maxq][],ans[maxq],qct;
int fa[maxn],dep[maxn],wson[maxn],siz[maxn],top[maxn],root[maxn],len[maxn];
int ch[maxn*][],val[maxn*],pct;
bool laz[maxn*];
map<int,int> mp; inline void adeg(int a,int b){
eg[ect].a=a;eg[ect].b=b;eg[ect].ne=egh[a];eg[ect].used=;egh[a]=ect++;
} inline void pushdown(int p){
if(!laz[p]) return;
val[ch[p][]]=val[ch[p][]]=laz[p]=;
laz[ch[p][]]=laz[ch[p][]]=;
}
inline void update(int p){pushdown(p);val[p]=val[ch[p][]]+val[ch[p][]];} void build(int &p,int l,int r){
p=++pct;
if(l==r) val[p]=;
else{
int m=l+r>>;
build(ch[p][],l,m);build(ch[p][],m+,r);
update(p);
}
} int query(int p,int l,int r,int x,int y){
if(x<=l&&r<=y) return val[p];
else{
pushdown(p);int m=l+r>>,re=;
if(x<=m) re+=query(ch[p][],l,m,x,y);
if(y>=m+) re+=query(ch[p][],m+,r,x,y);
return re;
}
} void change(int p,int l,int r,int x,int y){
if(x<=l&&r<=y){
val[p]=;laz[p]=;pushdown(p);
}else if(val[p]!=){
pushdown(p);int m=l+r>>;
if(x<=m) change(ch[p][],l,m,x,y);
if(y>=m+) change(ch[p][],m+,r,x,y);
update(p);
}
} void dfs1(int x){
siz[x]=;int ma=;
for(int i=egh[x];i!=-;i=eg[i].ne){
int b=eg[i].b;
if(!eg[i].used||dep[b]) continue;
eg[i].flag=eg[i^].flag=;
fa[b]=x;dep[b]=dep[x]+;
dfs1(b);siz[x]+=siz[b];
if(siz[b]>ma) ma=siz[b],wson[x]=b;
}
} void dfs2(int x){
if(x!=wson[fa[x]]){int d=;
for(int i=x;i;i=wson[i]) top[i]=x,d++;
build(root[x],,d);len[x]=d;
}for(int i=egh[x];i!=-;i=eg[i].ne){
int b=eg[i].b;
if(eg[i].flag&&fa[x]!=b) dfs2(b);
}
} void solveC(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
change(root[top[x]],,len[top[x]],,dep[x]-dep[top[x]]+);x=fa[top[x]];
}if(x==y) return;
if(dep[x]>dep[y]) swap(x,y);
change(root[top[x]],,len[top[x]],dep[x]-dep[top[x]]+,dep[y]-dep[top[y]]+);
}
int solveQ(int x,int y){
int re=;
while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y);
re+=query(root[top[x]],,len[top[x]],,dep[x]-dep[top[x]]+);x=fa[top[x]];
}if(x==y) return re;
if(dep[x]>dep[y]) swap(x,y);
return re+query(root[top[x]],,len[top[x]],dep[x]-dep[top[x]]+,dep[y]-dep[top[y]]+);
} int main(){
int i,j,k;
N=rd();M=rd();memset(egh,-,sizeof(egh));
for(i=;i<=M;i++){
int a=rd(),b=rd();
mp[a*N+b]=ect;adeg(a,b);
mp[b*N+a]=ect;adeg(b,a);
}while(++qct){
int a=rd();if(a==-) break;
int b=rd(),c=rd();
que[qct][]=a;que[qct][]=b;que[qct][]=c;
if(!a){
int x=mp[b*N+c];
eg[x].used=eg[x^].used=;
}
}dep[]=;dfs1();dfs2();
for(i=;i<ect;i++){
if((!eg[i].flag)&&eg[i].used) solveC(eg[i].a,eg[i].b);
}int act=;
for(i=qct-;i;i--){
if(!que[i][]) solveC(que[i][],que[i][]);
else ans[++act]=solveQ(que[i][],que[i][]);
}for(i=act;i;i--) printf("%d\n",ans[i]);
return ;
}
luogu2542 航线规划 (树链剖分)的更多相关文章
- BZOJ 1969: [Ahoi2005]LANE 航线规划( 树链剖分 )
首先我们要时光倒流, 倒着做, 变成加边操作维护关键边. 先随意搞出一颗树, 树上每条边都是关键边(因为是树, 去掉就不连通了)....然后加边(u, v)时, 路径(u, v)上的所有边都变成非关键 ...
- 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树
题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...
- BZOJ 1969: [Ahoi2005]LANE 航线规划 [树链剖分 时间倒流]
题意: 一张图,删除边,求两点之间的割边数量.保证任意时刻图连通 任求一棵生成树,只有树边可能是割边 时间倒流,加入一条边,就是两点路径上的边都不可能是割边,区间覆盖... 然后本题需要把边哈希一下, ...
- bzoj1969 [Ahoi2005]LANE 航线规划 树链剖分
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1969 题解 如果我们把整个图边双联通地缩点,那么最终会形成一棵树的样子. 那么在这棵树上,\( ...
- 洛谷 P2542 [AHOI2005]航线规划 树链剖分_线段树_时光倒流_离线
Code: #include <map> #include <cstdio> #include <algorithm> #include <cstring&g ...
- 【bzoj2402】陶陶的难题II 分数规划+树链剖分+线段树+STL-vector+凸包+二分
题目描述 输入 第一行包含一个正整数N,表示树中结点的个数.第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5).第三行包含N个正实数,第i个数表示yi (1<=yi& ...
- 【BZOJ2402】陶陶的难题II 分数规划+树链剖分+线段树+凸包
题解: 首先分数规划是很明显的 然后在于我们如何要快速要求yi-mid*xi的最值 这个是看了题解之后才知道的 这个是斜率的一个基本方法 我们设y=mid*x+z 那么显然我们可以把(x,y)插入到一 ...
- bzoj1969: [Ahoi2005]LANE 航线规划(树链剖分)
只有删边,想到时间倒流. 倒着加边,因为保证图连通,所以一开始一定至少是一棵树.我们先建一棵树出来,对于每一条非树边,两个端点在树上这段路径的边就不会变成关键边了,所以将它们对答案的贡献删去,那么直接 ...
- [BZOJ2402]陶陶的难题II(树链剖分+线段树维护凸包+分数规划)
陶陶的难题II 时间限制:40s 空间限制:128MB 题目描述 输入格式 第一行包含一个正整数N,表示树中结点的个数. 第二行包含N个正实数,第i个数表示xi (1<=xi<= ...
随机推荐
- SAAS云平台搭建札记: (二) Linux Ubutu下.Net Core整套运行环境的搭建
最近做的项目,由于预算有限,公司决定不采购Windows服务器,而采购基于Linux的服务器. 一般的VPS服务器,如果使用Windows系统,那么Windows Server2012\2016安装好 ...
- SQL行转列汇总 (转)
PIVOT 用于将列值旋转为列名(即行转列),在 SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT 的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )A ...
- 腾讯云COS体验
其实这篇文章本来是推荐COS的,写了一半发现COS的免费额度取消了,2019年之后的开通的用户免费6个月,老用户不受影响,这还让我怎么推荐啊?!写都写了,删掉岂不是白浪费时间? 都怪你!腾讯云! 起因 ...
- Ceph分布式存储-原理介绍及简单部署
1)Ceph简单概述Ceph是一个分布式存储系统,诞生于2004年,最早致力于开发下一代高性能分布式文件系统的项目.Ceph源码下载:http://ceph.com/download/.随着云计算的发 ...
- vue element-ui 动态上传
上传填写完毕的幼儿及体测数据文件,上传成功后会自动导入该文件的数据 <el-upload :action="UploadUrl()" :on-success="Up ...
- 结对项目https://github.com/bxoing1994/test/blob/master/源代码
所选项目名称:文本替换 结对人:曲承玉 github地址 :https://github.com/bxoing1994/test/blob/master/源代码 结对人github地址:ht ...
- pandas获取groupby分组里最大值所在的行,获取第一个等操作
pandas获取groupby分组里最大值所在的行 10/May 2016 python pandas pandas获取groupby分组里最大值所在的行 如下面这个DataFrame,按照Mt分组, ...
- Jenkins 登录提示 登录无效 的解决办法
学习自:https://www.cnblogs.com/amberly/p/6288773.html 1. jenkins服务器重启之后, 再次登录提示登录无效. 重启多次也无法解决. 2. 根据文档 ...
- Linux查看版本
最简单的命令 lsb_release -a 查看机器名 hostname 查看内核版本 uname -r 红帽 centos 查看版本 cat /etc/redhat-release ubuntu 查 ...
- C++与C的区别
在最开始C++只是C加上了一些面向对象的特性,C++最初的名字为C with Classes.后来C++又提出了一些不同于Class的特性:Exceptions(异常).templates(模板).S ...