Codeforces 938G Shortest Path Queries

一张连通图,三种操作

1.给x和y之间加上边权为d的边,保证不会产生重边

2.删除x和y之间的边,保证此边之前存在

3.询问x到y的路径异或最小值

保证图在任意时刻连通

首先连通图路径异或相当于从x到y的任意一条路径再异或上若干个环得到的,只要在dfs过程中把非树边成的环丢到线性基里就好了,其他环一定可以通过这些环异或组合出来

有加边删边操作怎么做呢?线段树时间分治!注意到不能保证在线段树的任意一个节点图是连通的,需要用可撤销并查集来维护,总复杂度\(O(q\log(n)\log(q))\)

tips:其实线性基因为一次插入只有一个赋值操作也可以用同样的方式撤销,不一定要每次都复制一遍下传

//segment tree divide and conquer
//linear base, dsu(rollback)
#include <bits/stdc++.h>
using namespace std; const int N = 2e5 + 10; struct Linear_Base {
int a[30];
Linear_Base() {memset(a, 0, sizeof(a));}
void insert(int val) {
for(int i = 29; ~i; --i) {
if((val >> i) & 1) {
if(a[i] == 0) {
a[i] = val;
return;
}
val ^= a[i];
}
}
}
int query(int val) {
for(int i = 29; ~i; --i)
val = min(val, val ^ a[i]);
return val;
}
}; pair<int*, int> save[N * 10];
int top; void change(int &address, int val) {
save[top++] = make_pair(&address, address);
address = val;
} void rollback(int st) {
while(st != top) {
top--;
*save[top].first = save[top].second;
}
} struct edge {
int x, y, d;
edge() {x = y = d = 0;}
edge(int _x, int _y, int _d) : x(_x), y (_y), d(_d) {}
}; struct que {
int x, y, id;
que() {x = y = id = 0;}
que(int _x, int _y, int _id) : x(_x), y (_y), id(_id) {}
}; int ans[N], tot; vector<edge> G[N << 2];
vector<que> Q[N << 2]; int dsu[N], size[N], dis[N]; int find(int x) {
return x == dsu[x] ? x : find(dsu[x]);
} int get_dist(int x) {
return x == dsu[x] ? 0 : dis[x] ^ get_dist(dsu[x]);
} int unite(int x, int y, int d) {
d ^= get_dist(x);
d ^= get_dist(y);
x = find(x);
y = find(y);
if(x == y)
return 0;
if(size[x] < size[y]) swap(x, y);
change(size[x], size[x] + size[y]);
change(dsu[y], x);
change(dis[y], d);
return 1;
} void update(int rt, int l, int r, int L, int R, const edge &x) {
if(L <= l && r <= R) {G[rt].push_back(x); return;}
int mid = l + r >> 1;
if(L <= mid) update(rt << 1, l, mid, L, R, x);
if(R > mid) update(rt << 1 | 1, mid + 1, r, L, R, x);
} void add_query(int rt, int l, int r, int pos, const que &x) {
if(l == r) {Q[rt].push_back(x); return;}
int mid = l + r >> 1;
if(pos <= mid) add_query(rt << 1, l, mid, pos, x);
else add_query(rt << 1 | 1, mid + 1, r, pos, x);
} void dfs(int rt, int l, int r, Linear_Base Base) {
int st = top;
for(auto e : G[rt]) {
if(!unite(e.x, e.y, e.d)) {
Base.insert(get_dist(e.x) ^ get_dist(e.y) ^ e.d);
}
}
if(l == r) {
for(auto q : Q[rt])
ans[q.id] = Base.query(get_dist(q.x) ^ get_dist(q.y));
}
else {
int mid = l + r >> 1;
dfs(rt << 1, l, mid, Base);
dfs(rt << 1 | 1, mid + 1, r, Base);
}
rollback(st);
} int n, m, q, op, x, y, d;
map<pair<int, int>, pair<int, int>> st; int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) dsu[i] = i, size[i] = 1, dis[i] = 0;
for(int i = 1; i <= m; ++i) {
scanf("%d%d%d", &x, &y, &d);
st[make_pair(x, y)] = make_pair(1, d);
}
scanf("%d", &q);
for(int i = 1; i <= q; ++i) {
scanf("%d%d%d", &op, &x, &y);
if(op == 1) {
scanf("%d", &d);
st[make_pair(x, y)] = make_pair(i, d);
}
else if(op == 2) {
update(1, 1, q, st[make_pair(x, y)].first, i, edge(x, y, st[make_pair(x, y)].second));
st.erase(make_pair(x, y));
}
else {
add_query(1, 1, q, i, que(x, y, ++tot));
}
}
for(auto e: st) {
update(1, 1, q, e.second.first, q, edge(e.first.first, e.first.second, e.second.second));
}
dfs(1, 1, q, Linear_Base());
for(int i = 1; i <= tot; ++i) {
printf("%d\n", ans[i]);
}
return 0;
}

Codeforces 938G 线段树分治 线性基 可撤销并查集的更多相关文章

  1. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

  2. $CF938G\ Shortest\ Path\ Queries$ 线段树分治+线性基

    正解:线段树分治+线性基 解题报告: 传送门$QwQ$ 考虑如果只有操作3,就这题嘛$QwQ$ 欧克然后现在考虑加上了操作一操作二 于是就线段树分治鸭 首先线段树叶子节点是询问嘛这个不用说$QwQ$. ...

  3. 【luogu3733】【HAOI2017】 八纵八横 (线段树分治+线性基)

    Descroption 原题链接 给你一个\(n\)个点的图,有重边有自环保证连通,最开始有\(m\)条固定的边,要求你支持加边删边改边(均不涉及最初的\(m\)条边),每一次操作都求出图中经过\(1 ...

  4. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset

    题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...

  5. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

  6. BZOJ4184:shallot(线段树分治,线性基)

    Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且 让小葱 ...

  7. bzoj 4184 shallot——线段树分治+线性基

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4184 本来想了可持久化trie,不过空间是 nlogn (出一个节点的时候把 tot 复原就 ...

  8. bzoj 4184: shallot (线段树维护线性基)

    题面 \(solution:\) 这一题绝对算的上是一道经典的例题,它向我们诠释了一种新的线段树维护方式(神犇可以跳过了).像这一类需要加入又需要维护删除的问题,我们曾经是遇到过的像莫对,线段树... ...

  9. BZOJ4025: 二分图【线段树分治】【带撤销的并查集】

    Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. Input ...

随机推荐

  1. js实现点击空白处隐藏

    部分业务要求除了某元素外点击其他对象,对应的元素隐藏,下面是一个demo效果, <!DOCTYPE html> <html> <head> <meta cha ...

  2. Odoo Javascript 参考

    本文介绍了odoo javascript框架.从代码行的角度来看,这个框架不是一个大的应用程序,但它是非常通用的,因为它基本上是一个将声明性接口描述转换为活动应用程序的机器,能够与数据库中的每个模型和 ...

  3. SQL Server SQLGetData()

    { /* 语法 C++ SQLRETURN SQLGetData( SQLHSTMT StatementHandle, SQLUSMALLINT Col_or_Param_Num, SQLSMALLI ...

  4. 11_springmvc之RESTful支持

    一.理解RESTful RESTful架构,就是一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. RESTful(即Representational Sta ...

  5. 收藏的链接-Git

    git远程删除分支后,本地git branch -a 依然能看到的解决办法. - qq_763034592的博客 - CSDN博客 https://blog.csdn.net/qq_16885135/ ...

  6. linux常用软连接使用ln -s

    [软连接]另外一种连接称之为符号连接(Symbolic Link),也叫软连接.软链接文件有类似于Windows的快捷方式.它实际上是一个特殊的文件.在符号连接中,文件实际上是一个文本文件,其中包含的 ...

  7. Django中static文件的引入

    1. 在django project中创建 static文件夹 2.settings.py中配置要在 STATIC_URL = '/static/'  下边 STATICFILES_DIRS = [ ...

  8. 2019-8-31-dotnet-获取指定进程的输入命令行

    title author date CreateTime categories dotnet 获取指定进程的输入命令行 lindexi 2019-08-31 16:55:58 +0800 2019-0 ...

  9. 对this的理解与总结

    this既不指向函数自身,也不指向函数的词法作用域!它指向谁完全取决于它在哪里被调用,被谁调用! 绑定规则 总体来说,this的绑定规则有: 默认绑定(严格模式/非严格模式) 隐式绑定 显式绑定 ne ...

  10. Extjs & Ext.net中的一些属性

    Extjs & Ext.Net 弹出整个浏览器对话框的方法 top.Ext.Msg.alert("值"); top.Ext.Msg.confirm("值" ...