题解 CF938G 【Shortest Path Queries】
题目让我们维护一个连通无向图,边有边权,支持加边删边和询问从\(x\)到\(y\)的异或最短路。
考虑到有删边这样的撤销操作,那么用线段树分治来实现,用线段树来维护询问的时间轴。
将每一条边的出现时间段标记到线段树上,表示在这一段询问中这条边存在。
异或最短路的处理方法与最大XOR和路径类似,给线段树上每个节点开一个线性基,找出当前所有的环,插入该节点的线性基,查询时任意找出一条从\(x\)到\(y\)的路径,到线性基中查询,即为答案。
具体实现时用可撤销并查集,采用按秩合并来优化,因为路径压缩会破坏树的结构。
具体实现细节看代码吧。
\(code:\)
#include<bits/stdc++.h>
#define maxn 400010
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,m,q,num,tree_cnt,edge_cnt,root,top;
int ls[maxn],rs[maxn],pre[maxn],nxt[maxn],ans[maxn];
map<pair<int,int>,int> mp;
struct Edge
{
int x,y,v;
}e[maxn];
struct node
{
int x,y,deep;
}st[maxn];
struct query
{
int x,y;
}qu[maxn];
void build(int l,int r,int &cur)
{
if(!cur) cur=++tree_cnt;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,ls[cur]);
build(mid+1,r,rs[cur]);
}
vector<int> v[maxn];
void insert(int L,int R,int l,int r,int id,int cur)
{
if(L<=l&&R>=r)
{
v[cur].push_back(id);
return;
}
int mid=(l+r)>>1;
if(L<=mid) insert(L,R,l,mid,id,ls[cur]);
if(R>mid) insert(L,R,mid+1,r,id,rs[cur]);
}
int a[maxn][40];
void ins(int x,int cur)
{
for(int i=30;i>=0;--i)
{
if(x&(1<<i))
{
if(!a[cur][i])
{
a[cur][i]=x;
break;
}
else x^=a[cur][i];
}
}
}
int get(int x,int cur)
{
for(int i=30;i>=0;--i)
if((x^a[cur][i])<x)
x^=a[cur][i];
return x;
}
int fa[maxn],de[maxn],dis[maxn];
int find(int x)
{
return fa[x]==x?x:find(fa[x]);
}
int xor_dis(int x)
{
return fa[x]==x?dis[x]:dis[x]^xor_dis(fa[x]);
}
void merge(int x,int y,int v)
{
if(de[x]<de[y]) swap(x,y);
st[++top]=(node){x,y,de[x]};
fa[y]=x,dis[y]=v,de[x]=max(de[x],de[y]+1);
}
void del(int id)
{
int x=st[id].x,y=st[id].y;
fa[y]=y,dis[y]=0,de[x]=st[id].deep;
}
void copy(int x,int y)
{
for(int i=0;i<=30;++i) a[y][i]=a[x][i];
}
void dfs(int l,int r,int cur)
{
int now=top,size=v[cur].size();
for(int i=0;i<size;++i)
{
int id=v[cur][i],x=e[id].x,y=e[id].y,v=e[id].v;
v^=xor_dis(x)^xor_dis(y),x=find(x),y=find(y);
if(x==y) ins(v,cur);
else merge(x,y,v);
}
if(l==r)
{
int x=qu[l].x,y=qu[l].y;
ans[l]=get(xor_dis(x)^xor_dis(y),cur);
}
else
{
int mid=(l+r)>>1;
copy(cur,ls[cur]),dfs(l,mid,ls[cur]);
copy(cur,rs[cur]),dfs(mid+1,r,rs[cur]);
}
while(top>now) del(top--);
}
int main()
{
read(n),read(m),edge_cnt=m;
for(int i=1;i<=n;++i) fa[i]=i;
for(int i=1;i<=m;++i)
{
read(e[i].x),read(e[i].y),read(e[i].v);
mp[make_pair(e[i].x,e[i].y)]=i,pre[i]=1,nxt[i]=-1;
}
read(q);
while(q--)
{
int opt,x,y,v;
read(opt);
if(opt==1)
{
read(x),read(y),read(v);
e[++edge_cnt]=(Edge){x,y,v};
mp[make_pair(x,y)]=edge_cnt;
pre[edge_cnt]=num+1,nxt[edge_cnt]=-1;
}
if(opt==2)
{
read(x),read(y);
nxt[mp[make_pair(x,y)]]=num;
}
if(opt==3)
{
read(x),read(y);
qu[++num]=(query){x,y};
}
}
build(1,num,root);
for(int i=1;i<=edge_cnt;++i)
{
if(nxt[i]<0) nxt[i]=num;
if(pre[i]<=nxt[i]) insert(pre[i],nxt[i],1,num,i,root);
}
dfs(1,num,root);
for(int i=1;i<=num;++i)
printf("%d\n",ans[i]);
return 0;
}
题解 CF938G 【Shortest Path Queries】的更多相关文章
- CF938G Shortest Path Queries 和 CF576E Painting Edges
这两道都用到了线段树分治和按秩合并可撤销并查集. Shortest Path Queries 给出一个连通带权无向图,边有边权,要求支持 q 个操作: x y d 在原图中加入一条 x 到 y 权值为 ...
- CF938G Shortest Path Queries
首先只有询问的话就是个WC的题,线性基+生成树搞一搞就行. 进一步,考虑如果修改操作只有加边怎么做. 好像也没有什么变化,只不过需要在线地往线性基里插入东西而已. 删边呢? 注意到线性基这个玩意是不支 ...
- $CF938G\ Shortest\ Path\ Queries$ 线段树分治+线性基
正解:线段树分治+线性基 解题报告: 传送门$QwQ$ 考虑如果只有操作3,就这题嘛$QwQ$ 欧克然后现在考虑加上了操作一操作二 于是就线段树分治鸭 首先线段树叶子节点是询问嘛这个不用说$QwQ$. ...
- 【CF938G】Shortest Path Queries(线段树分治,并查集,线性基)
[CF938G]Shortest Path Queries(线段树分治,并查集,线性基) 题面 CF 洛谷 题解 吼题啊. 对于每个边,我们用一个\(map\)维护它出现的时间, 发现询问单点,边的出 ...
- Codeforces 938G Shortest Path Queries [分治,线性基,并查集]
洛谷 Codeforces 分治的题目,或者说分治的思想,是非常灵活多变的. 所以对我这种智商低的选手特别不友好 脑子不好使怎么办?多做题吧-- 前置知识 线性基是你必须会的,不然这题不可做. 推荐再 ...
- CF 938G Shortest Path Queries
又到了喜闻乐见的写博客清醒时间了233,今天做的依然是线段树分治 这题算是经典应用了吧,假的动态图(可离线)问题 首先不难想到对于询问的时间进行线段树分治,这样就可以把每一条边出现的时间区间扔进线段树 ...
- Shortest Path(思维,dfs)
Shortest Path Accepts: 40 Submissions: 610 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: ...
- HDU 5636 Shortest Path 暴力
Shortest Path 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5636 Description There is a path graph ...
- Shortest Path
Shortest Path Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...
随机推荐
- Spring Cloud面试题万字解析(2020面试必备)
1.什么是 Spring Cloud? Spring cloud 流应用程序启动器是 于 Spring Boot 的 Spring 集成应用程序,提供与外部系统的集成.Spring cloud Tas ...
- .NETCore微服务探寻(二) - 认证与授权
前言 一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目 ...
- Electron: 如何以 Vue.js, Vuetify 开始应用
Electron: 使用 JavaScript, HTML 和 CSS 等 Web 技术创建原生程序的框架 Vue.js: Web 前端用于构建用户界面的渐进式框架 Vuetify: Vue.js 的 ...
- P1131 [ZJOI2007]时态同步【树形dp】
时态同步 从叶子到根节点统计修改次数.树形\(dp\)思想. 题目描述 小\(Q\)在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字\(1,2,3-\). ...
- 教你如何开发一个完败Miracast的投屏新功能
手机与电视,是陪伴在我们生活最常见,陪伴最长久的智能设备.迅猛发展的移动终端与通信技术,赋予了手机更广阔多元的应用生态,大屏电视则以大视野和震撼影音,弥补了手里方寸带来的视觉局限.而今,手机的延伸 ...
- Redis系列(九):数据结构Hash之HDEL、HEXISTS、HGETALL、HKEYS、HLEN、HVALS命令
1.HDEL 从 key 指定的哈希集中移除指定的域.在哈希集中不存在的域将被忽略. 如果 key 指定的哈希集不存在,它将被认为是一个空的哈希集,该命令将返回0. 时间复杂度:O(N) N是被删除的 ...
- 安装完kali linux之后要做的10件事——113p.cn
1.添加国内更新源(可能不是最好的) vim /etc/apt/source.list 科技大学# deb http://mirrors.ustc.edu.cn/kali sana main non- ...
- 【蓝桥杯】2018年第九届蓝桥杯C/C++B组省赛——B题 等差素数列
题目 标题:等差素数列 2,3,5,7,11,13,....是素数序列. 类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列. 上边的数列公差为30,长度为6. ...
- 每日一题 - 剑指 Offer 32 - II. 从上到下打印二叉树 II
题目信息 时间: 2019-06-25 题目链接:Leetcode tag: 队列 BFS 难易程度:简单 题目描述: 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行. 示 ...
- 常见Python的Web开发框架
在今天,Python里有很多开发框架用来帮助你轻松创建web应用.web开发框架存在的意义就在于可以快速便捷的构建应用,而不用去在意那些没必要的技术细节(协议.报文.数据结构). 到2020年为止,基 ...