不会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 航线规划 (树链剖分)的更多相关文章

  1. BZOJ 1969: [Ahoi2005]LANE 航线规划( 树链剖分 )

    首先我们要时光倒流, 倒着做, 变成加边操作维护关键边. 先随意搞出一颗树, 树上每条边都是关键边(因为是树, 去掉就不连通了)....然后加边(u, v)时, 路径(u, v)上的所有边都变成非关键 ...

  2. 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  3. BZOJ 1969: [Ahoi2005]LANE 航线规划 [树链剖分 时间倒流]

    题意: 一张图,删除边,求两点之间的割边数量.保证任意时刻图连通 任求一棵生成树,只有树边可能是割边 时间倒流,加入一条边,就是两点路径上的边都不可能是割边,区间覆盖... 然后本题需要把边哈希一下, ...

  4. bzoj1969 [Ahoi2005]LANE 航线规划 树链剖分

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1969 题解 如果我们把整个图边双联通地缩点,那么最终会形成一棵树的样子. 那么在这棵树上,\( ...

  5. 洛谷 P2542 [AHOI2005]航线规划 树链剖分_线段树_时光倒流_离线

    Code: #include <map> #include <cstdio> #include <algorithm> #include <cstring&g ...

  6. 【bzoj2402】陶陶的难题II 分数规划+树链剖分+线段树+STL-vector+凸包+二分

    题目描述 输入 第一行包含一个正整数N,表示树中结点的个数.第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5).第三行包含N个正实数,第i个数表示yi (1<=yi& ...

  7. 【BZOJ2402】陶陶的难题II 分数规划+树链剖分+线段树+凸包

    题解: 首先分数规划是很明显的 然后在于我们如何要快速要求yi-mid*xi的最值 这个是看了题解之后才知道的 这个是斜率的一个基本方法 我们设y=mid*x+z 那么显然我们可以把(x,y)插入到一 ...

  8. bzoj1969: [Ahoi2005]LANE 航线规划(树链剖分)

    只有删边,想到时间倒流. 倒着加边,因为保证图连通,所以一开始一定至少是一棵树.我们先建一棵树出来,对于每一条非树边,两个端点在树上这段路径的边就不会变成关键边了,所以将它们对答案的贡献删去,那么直接 ...

  9. [BZOJ2402]陶陶的难题II(树链剖分+线段树维护凸包+分数规划)

    陶陶的难题II 时间限制:40s      空间限制:128MB 题目描述 输入格式 第一行包含一个正整数N,表示树中结点的个数. 第二行包含N个正实数,第i个数表示xi (1<=xi<= ...

随机推荐

  1. 苹果企业账号打包发布App的详细流程

    原文链接:http://www.cnblogs.com/mddblog/p/4718228.html 一.通过企业账号申请证书 1 Certificate Signing Request (CSR)文 ...

  2. .net core实践系列之短信服务-为什么选择.net core(开篇)

    前言 从今天我将会写.net core实战系列,以我最近完成的短信服务作为例子.该系列将会尽量以最短的时间全部发布出来.源码也将优先开源出来给大家. 源码地址:https://github.com/S ...

  3. copy constructor

    copy constructor也分为trivial和nontrivial两种 如果class展现出bitwise copy semantics(按位拷贝语义),则不会构造出 copy constru ...

  4. RabbitMQ TroubleShooting

    RabbitMQ是一款优秀的消息队列中间件,提供了稳定.监控完善的产品,但是软件就会有bug.为了前进路径可以畅通,我们必须了解出现的一些故障的快速处理方式,毕竟在生产环境,时间就是生命,尽快的处理是 ...

  5. 将 C# 枚举序列化为 JSON 字符串 基础理论

    该转换过程需要引用 Newtonsoft.JSON,这其中的转换过程还是蛮有意思的. 一.定义枚举 /// <summary> /// 托寄物品枚举 /// </summary> ...

  6. Aop笔记

    参考: https://blog.csdn.net/bombSKLK/article/details/79143145 示例 拦截的 注解的方法 @Around("@annotation(c ...

  7. Visual Studio平台安装及测试

    一.VS安装 图1.1 图1.2 二.单元测试练习 题目:课本22~25页单元测试练习 1.创建一个c#类(具体如下:打开VS2010,然后点击VS界面上左上角的文件按钮,然后点击文件—新建—项目,就 ...

  8. pair work结对编程(张艺 杨伊)

    一.结对编程人员: 张艺(学号后三位:185) 杨伊(学号后三位:151) 二.这是我们工作的样子:(图片) 三.结对编程优缺点:  优点:  1.结对编程时间紧密,在一定程度上可以督促双方学习,提高 ...

  9. Linux内核第四节 20135332武西垚

    实验目的: 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 实验过程: 查看系统调用列表 get pid 函数 #include <stdio.h> #include & ...

  10. JAVA面对对象(三)——Super、static、final关键字

    Super 使用super关键字可以直接调用父类中的构造方法.属性.普通方法 super调用父类构造方法的操作,与this调用构造方法一样,语句必须放在子类构造方法的首行 public class P ...