又到了喜闻乐见的写博客清醒时间了233,今天做的依然是线段树分治

这题算是经典应用了吧,假的动态图(可离线)问题

首先不难想到对于询问的时间进行线段树分治,这样就可以把每一条边出现的时间区间扔进线段树里,考虑如何维护答案

初步的想,图上两点间异或最小值,和最大值类似。先求出一棵生成树,然后把环扔进线性基里,每次查询两点间异或值之后再扔进线性基里求最小值即可

正确性的话,因为这样环一定是有树边+非树边构成的,我们可以在任意一个点走到一个环再绕回来,中间重复走的树边因为走了两次相当于没有影响

然后我们惊喜地发现,线性基是支持撤销的,而且两点间异或值可以用带撤销并查集来做,然后线段树分治的时候回溯的时候撤销即可

然后就做完了,总复杂度\(O(n\log^2 n)\),足以通过此题

说句题外话,那个维护两点间距离的并查集我本来准备用我的可换根并查集来写了,但是发现换根操作的逆过程(即撤销)比较难写,所以最后不得已向差分低头

  1. #include<cstdio>
  2. #include<cctype>
  3. #include<iostream>
  4. #include<vector>
  5. #include<utility>
  6. #include<map>
  7. #define RI register int
  8. #define CI const int&
  9. #define Tp template <typename T>
  10. #define mp make_pair
  11. using namespace std;
  12. typedef pair <int,int> pi;
  13. const int N=200005,R=30;
  14. struct edge
  15. {
  16. int x,y,v,s,t;
  17. }e[N<<1]; int n,m,q,opt,cnt,tim,x,y,qx[N],qy[N],top; map <pi,int> Hash;
  18. class FileInputOutput
  19. {
  20. private:
  21. static const int S=1<<21;
  22. #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
  23. #define pc(ch) (Ftop!=Fend?*Ftop++=ch:(fwrite(Fout,1,S,stdout),*(Ftop=0)++=ch))
  24. char Fin[S],Fout[S],*A,*B,*Ftop,*Fend; int pt[15];
  25. public:
  26. inline FileInputOutput(void) { Ftop=Fout; Fend=Fout+S; }
  27. Tp inline void read(T& x)
  28. {
  29. x=0; char ch; while (!isdigit(ch=tc()));
  30. while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
  31. }
  32. Tp inline void write(T x)
  33. {
  34. RI ptop=0; while (pt[++ptop]=x%10,x/=10);
  35. while (ptop) pc(pt[ptop--]+48); pc('\n');
  36. }
  37. inline void flush(void)
  38. {
  39. fwrite(Fout,1,Ftop-Fout,stdout);
  40. }
  41. #undef tc
  42. #undef pc
  43. }F;
  44. class Linear_Basis
  45. {
  46. private:
  47. int r[100][R];
  48. public:
  49. inline void insert(int x,CI dep)
  50. {
  51. for (RI i=R-1;~i;--i) if ((x>>i)&1)
  52. if (r[dep][i]) x^=r[dep][i]; else
  53. {
  54. r[dep][i]=x; for (RI j=R-1;j>i;--j)
  55. if ((r[dep][j]>>i)&1) r[dep][j]^=x; break;
  56. }
  57. }
  58. inline int query(int ret,CI dep)
  59. {
  60. for (RI i=R-1;~i;--i) if (r[dep][i]) ret=min(ret,ret^r[dep][i]); return ret;
  61. }
  62. inline void copy(CI dep)
  63. {
  64. for (RI i=0;i<R;++i) r[dep][i]=r[dep-1][i];
  65. }
  66. }LB;
  67. class UnionFindSet
  68. {
  69. private:
  70. int fa[N],size[N],val[N],stk[N];
  71. inline int getfa(CI x)
  72. {
  73. return x!=fa[x]?getfa(fa[x]):x;
  74. }
  75. public:
  76. inline void init(void)
  77. {
  78. for (RI i=1;i<=n;++i) fa[i]=i,size[i]=1;
  79. }
  80. inline int getval(CI x)
  81. {
  82. return x!=fa[x]?val[x]^getval(fa[x]):0;
  83. }
  84. inline int identify(CI x,CI y)
  85. {
  86. return getfa(x)==getfa(y);
  87. }
  88. inline void Union(int x,int y,CI v)
  89. {
  90. x=getfa(x); y=getfa(y); if (size[x]>size[y]) swap(x,y);
  91. fa[x]=y; size[y]+=size[x]==size[y]; val[x]=v^val[x]; stk[++top]=x;
  92. }
  93. inline void revoke(CI tar)
  94. {
  95. int x; while (top>tar) x=stk[top--],size[fa[x]]-=(size[fa[x]]==size[x]+1),val[x]=0,fa[x]=x;
  96. }
  97. }S;
  98. class Segment_Tree
  99. {
  100. private:
  101. vector <int> pv[N<<2];
  102. inline void expand(CI now,CI dep)
  103. {
  104. for (vector <int>::iterator it=pv[now].begin();it!=pv[now].end();++it)
  105. {
  106. int x=e[*it].x,y=e[*it].y,v=S.getval(x)^S.getval(y)^e[*it].v;
  107. if (S.identify(x,y)) LB.insert(v,dep); else S.Union(x,y,v);
  108. }
  109. }
  110. inline void calc(CI now,CI pos,CI dep,CI tp)
  111. {
  112. int ans=S.getval(qx[pos])^S.getval(qy[pos]);
  113. F.write(LB.query(ans,dep)); S.revoke(tp);
  114. }
  115. public:
  116. #define TN CI now=1,CI l=1,CI r=tim
  117. #define LS now<<1,l,mid
  118. #define RS now<<1|1,mid+1,r
  119. inline void insert(CI beg,CI end,CI pos,TN)
  120. {
  121. if (beg>end) return; if (beg<=l&&r<=end) return (void)(pv[now].push_back(pos)); int mid=l+r>>1;
  122. if (beg<=mid) insert(beg,end,pos,LS); if (end>mid) insert(beg,end,pos,RS);
  123. }
  124. inline void solve(TN,CI dep=1)
  125. {
  126. int tp=top; expand(now,dep); if (l==r) return calc(now,l,dep,tp); int mid=l+r>>1;
  127. LB.copy(dep+1); solve(LS,dep+1); LB.copy(dep+1); solve(RS,dep+1); S.revoke(tp);
  128. }
  129. #undef TN
  130. #undef LS
  131. #undef RS
  132. }SEG;
  133. int main()
  134. {
  135. //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
  136. RI i; for (F.read(n),F.read(m),i=1;i<=m;++i)
  137. F.read(e[i].x),F.read(e[i].y),F.read(e[i].v),
  138. e[i].s=1,e[i].t=-1,Hash[mp(e[i].x,e[i].y)]=i;
  139. for (cnt=m,F.read(q),i=1;i<=q;++i)
  140. {
  141. F.read(opt); F.read(x); F.read(y); switch (opt)
  142. {
  143. case 1:
  144. e[++cnt].x=x; e[cnt].y=y; F.read(e[cnt].v);
  145. e[cnt].s=tim+1; e[cnt].t=-1; Hash[mp(x,y)]=cnt; break;
  146. case 2:
  147. e[Hash[mp(x,y)]].t=tim; Hash[mp(x,y)]=0; break;
  148. case 3:
  149. qx[++tim]=x; qy[tim]=y; break;
  150. }
  151. }
  152. if (!tim) return 0; for (i=1;i<=cnt;++i) if (!~e[i].t) e[i].t=tim;
  153. for (i=1;i<=cnt;++i) SEG.insert(e[i].s,e[i].t,i);
  154. return S.init(),SEG.solve(),F.flush(),0;
  155. }

CF 938G Shortest Path Queries的更多相关文章

  1. Codeforces 938G Shortest Path Queries [分治,线性基,并查集]

    洛谷 Codeforces 分治的题目,或者说分治的思想,是非常灵活多变的. 所以对我这种智商低的选手特别不友好 脑子不好使怎么办?多做题吧-- 前置知识 线性基是你必须会的,不然这题不可做. 推荐再 ...

  2. 【CF938G】Shortest Path Queries(线段树分治,并查集,线性基)

    [CF938G]Shortest Path Queries(线段树分治,并查集,线性基) 题面 CF 洛谷 题解 吼题啊. 对于每个边,我们用一个\(map\)维护它出现的时间, 发现询问单点,边的出 ...

  3. CF938G Shortest Path Queries 和 CF576E Painting Edges

    这两道都用到了线段树分治和按秩合并可撤销并查集. Shortest Path Queries 给出一个连通带权无向图,边有边权,要求支持 q 个操作: x y d 在原图中加入一条 x 到 y 权值为 ...

  4. CF938G Shortest Path Queries

    首先只有询问的话就是个WC的题,线性基+生成树搞一搞就行. 进一步,考虑如果修改操作只有加边怎么做. 好像也没有什么变化,只不过需要在线地往线性基里插入东西而已. 删边呢? 注意到线性基这个玩意是不支 ...

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

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

  6. 题解 CF938G 【Shortest Path Queries】

    题目让我们维护一个连通无向图,边有边权,支持加边删边和询问从\(x\)到\(y\)的异或最短路. 考虑到有删边这样的撤销操作,那么用线段树分治来实现,用线段树来维护询问的时间轴. 将每一条边的出现时间 ...

  7. Shortest Path(思维,dfs)

    Shortest Path  Accepts: 40  Submissions: 610  Time Limit: 4000/2000 MS (Java/Others)  Memory Limit: ...

  8. Shortest Path

    Shortest Path Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  9. 74(2B)Shortest Path (hdu 5636) (Floyd)

    Shortest Path Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

随机推荐

  1. Mysql中事务ACID实现原理

    引言 照例,我们先来一个场景~ 面试官:"知道事务的四大特性么?"你:"懂,ACID嘛,原子性(Atomicity).一致性(Consistency).隔离性(Isola ...

  2. 微信公众号开发 ,redirect_uri域名还是与后台配置不一致

    测试账号地址: https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index https ...

  3. python做中学(三)条件编译的用法

    C代码中经常使用条件编译,python中该怎么用呢?Python没有像C或C或Java甚至Java一样编译,python文件被“即时”编译,您可以将其视为类似于Basic或Perl的解释语言 只需使用 ...

  4. IT兄弟连 HTML5教程 HTML文档头部元素head

    HTML头部标记是<head>,主要包括页面的一些基本描述语句,以及CSS和JavaScript,一般都可以定义在头部元素中.它用于包含当前文档的有关信息,例如网页标题和关键字等.通常位于 ...

  5. 【Oracle命令】sql语句之排序(order by)

    通过对数据库数据进行降序排序来达到显示最新数据在前面的效果 -- 降序排序(最新的显示在前面) SELECT * FROM 表名 t ORDER BY t.uploadDatetime DESC; 格 ...

  6. win10启动telnet

    1.点击win菜单,点击设置图标 2.选择系统选项 3.选择应用与程序选项 4.拉到最下方,选择程序与功能 5.选择启用或关闭windows功能 6.下拉找到telnet客户端选项勾选

  7. centos7下编译安装python3.7,且与python2.7.5共存

    环境:Centos7.6 x64 一.安装python3.7 下载python源码包: wget https://www.python.org/ftp/python/3.7.4/Python-3.7. ...

  8. CTF 入门笔记

    站点:http://www.moctf.com/ web1:水题非常简单的题目,直接F12查看元素即可,在HTML代码中,flag被注释了. web2:水题 该题的核心 就是通过HTML代码对输入框进 ...

  9. Android Activity 开发常用技巧整理

    1.设置 Activity 背景色为透明 在style.xml里面声明: <style name="TranslucentActivityStyle" parent=&quo ...

  10. SoapUI、Postman测试WebService

    之前装了SoapUI,最近装了Postman,分别用它们测试了WebService,下面为用法. 测试的在线WebService(数据来源于中国气象局)Endpoint: http://www.web ...