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

题面

CF

洛谷

题解

吼题啊。

对于每个边,我们用一个\(map\)维护它出现的时间,

发现询问单点,边的出现时间是区间,所以线段树分治。

既然路径最小值就是异或最小值,并且可以不是简单路径,

不难让人想到\(WC2011\)那道最大\(Xor\)路径和。

用一样的套路,我们动态维护一棵生成树,碰到一个非树边,

就把这个环的异或和丢到线性基里面去,这样子直接查就好了。

动态维护生成树直接用并查集就好了,没有必要\(LCT\)

大概就是永远不进行路径压缩,每次启发式合并。

询问的时候暴跳父亲。

然后撤销操作的话,维护一个栈,每次存下当前的修改操作,

撤销的时候倒序还原就好了。

细节很多,第一次写这样的东西,调了好久啊。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<vector>
  8. #include<map>
  9. using namespace std;
  10. #define MAX 200200
  11. #define ll long long
  12. #define pi pair<int,int>
  13. #define mp(x,y) make_pair(x,y)
  14. #define lson (now<<1)
  15. #define rson (now<<1|1)
  16. inline int read()
  17. {
  18. int x=0;bool t=false;char ch=getchar();
  19. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  20. if(ch=='-')t=true,ch=getchar();
  21. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  22. return t?-x:x;
  23. }
  24. struct xxj
  25. {
  26. int p[31];
  27. void insert(int x)
  28. {
  29. for(int i=30;~i;--i)
  30. if(x&(1<<i))
  31. {
  32. if(!p[i]){p[i]=x;break;}
  33. x^=p[i];
  34. }
  35. }
  36. int Query(int x){for(int i=30;~i;--i)x=min(x,x^p[i]);return x;}
  37. }G;
  38. struct Node{int u,v,w;}p[MAX<<1];
  39. pi q[MAX];
  40. int n,m;
  41. map<pi,int> M;
  42. vector<Node> seg[MAX<<2];
  43. void Modify(int now,int l,int r,int L,int R,Node e)
  44. {
  45. if(L>R)return;if(L<=l&&r<=R){seg[now].push_back(e);return;}
  46. int mid=(l+r)>>1;
  47. if(L<=mid)Modify(lson,l,mid,L,R,e);
  48. if(R>mid)Modify(rson,mid+1,r,L,R,e);
  49. }
  50. int tim,cnt,L[MAX<<1],R[MAX<<1];
  51. int f[MAX],sz[MAX],Xor[MAX];
  52. int getf(int x){while(x!=f[x])x=f[x];return x;}
  53. int getxor(int x){int ret=0;while(x!=f[x])ret^=Xor[x],x=f[x];return ret;}
  54. void Divide(int now,int l,int r,xxj G)
  55. {
  56. vector<Node> c;c.clear();
  57. for(int i=0,lim=seg[now].size();i<lim;++i)
  58. {
  59. int u=seg[now][i].u,v=seg[now][i].v,w=seg[now][i].w;
  60. int f1=getf(u),f2=getf(v);
  61. if(f1==f2)G.insert(getxor(u)^getxor(v)^w);
  62. else
  63. {
  64. if(sz[f1]>sz[f2])swap(f1,f2),swap(u,v);
  65. w^=getxor(v)^getxor(u);
  66. c.push_back((Node){f1,f2,sz[f2]});
  67. Xor[f1]=w;f[f1]=f2;sz[f2]+=sz[f1];
  68. }
  69. }
  70. if(l==r)
  71. printf("%d\n",G.Query(getxor(q[l].first)^getxor(q[l].second)));
  72. else
  73. {
  74. int mid=(l+r)>>1;
  75. Divide(lson,l,mid,G);Divide(rson,mid+1,r,G);
  76. }
  77. for(int i=c.size()-1;~i;--i)
  78. {
  79. int u=c[i].u,v=c[i].v,w=c[i].w;
  80. sz[v]=w;f[u]=u;Xor[u]=0;
  81. }
  82. }
  83. int main()
  84. {
  85. //freopen("938G.in","r",stdin);
  86. //freopen("938G.out","w",stdout);
  87. n=read();m=read();
  88. for(int i=1;i<=m;++i)
  89. {
  90. int x=read(),y=read(),w=read();
  91. p[++cnt]=(Node){x,y,w};
  92. L[cnt]=1;M[mp(x,y)]=cnt;R[cnt]=-1;
  93. }
  94. int Q=read();
  95. for(int i=1;i<=Q;++i)
  96. {
  97. int opt=read(),x=read(),y=read();
  98. if(x>y)swap(x,y);
  99. if(opt==1)
  100. {
  101. p[++cnt]=(Node){x,y,read()};
  102. L[cnt]=tim+1;R[cnt]=-1;M[mp(x,y)]=cnt;
  103. }
  104. else if(opt==2)R[M[mp(x,y)]]=tim;
  105. else q[++tim]=mp(x,y);
  106. }
  107. for(int i=1;i<=cnt;++i)if(R[i]==-1)R[i]=tim;
  108. for(int i=1;i<=cnt;++i)Modify(1,1,tim,L[i],R[i],p[i]);
  109. for(int i=1;i<=n;++i)f[i]=i,sz[i]=1;
  110. Divide(1,1,tim,G);
  111. return 0;
  112. }

【CF938G】Shortest Path Queries(线段树分治,并查集,线性基)的更多相关文章

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

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

  2. 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)

    传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...

  3. bzoj4025二分图(线段树分治 并查集)

    /* 思维难度几乎没有, 就是线段树分治check二分图 判断是否为二分图可以通过维护lct看看是否链接出奇环 然后发现不用lct, 并查集维护奇偶性即可 但是复杂度明明一样哈 */ #include ...

  4. BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)

    Description Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connec ...

  5. BZOJ3237 AHOI2013连通图(线段树分治+并查集)

    把查询看做是在一条时间轴上.那么每条边都有几段存在时间.于是线段树分治就好了. 然而在bzoj上t掉了,不知道是常数大了还是写挂了. 以及brk不知道是啥做数组名过不了编译. #include< ...

  6. BZOJ4025 二分图(线段树分治+并查集)

    之前学了一下线段树分治,这还是第一次写.思想其实挺好理解,即离线后把一个操作影响到的时间段拆成线段树上的区间,并标记永久化.之后一块处理,对于某个节点表示的时间段,影响到他的就是该节点一直到线段树根的 ...

  7. Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)

    题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...

  8. BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)

    传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...

  9. [BZOJ4025]二分图(线段树分治,并查集)

    4025: 二分图 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2191  Solved: 800[Submit][Status][Discuss] ...

  10. Codeforces 1140F Extending Set of Points (线段树分治+并查集)

    这题有以下几个步骤 1.离线处理出每个点的作用范围 2.根据线段树得出作用范围 3.根据分治把每个范围内的点记录和处理 #include<bits/stdc++.h> using name ...

随机推荐

  1. JUC——延迟队列

    所谓的延迟队列最大的特征是它可以自动通过队列进行脱离,例如:现在有一些对象被临时保存着,但是有可能该集合对象是一个公共对象,那么里面的某些数据如果不在使用的时候就希望其可以在指定的时间达到后自动的消失 ...

  2. TP里where的查询方式,比如or应该怎么写?

    这应该是个基础..只是我没有系统的学TP,所以用到了临时查了手册. 正常来说,thinkphp里的查询方式是: ThinkPHP可以支持直接使用字符串作为查询条件,但是大多数情况推荐使用数组或者对象来 ...

  3. docker node项目 连接mongodb

    在弄docker部署node项目的时候遇到了连接mongdb的问题,记录一下问题解决办法 一.Docker 安装 MongoDB 1.查找Docker Hub上的mongo镜像 [root@VM_49 ...

  4. QT中的小细节

    一 .  QT4和QT5的区别(信号和槽):1.  QT4: connect(button,SIGNAL(pressed()),this,SLOT(close())); /** * 优点 :写法简单 ...

  5. spring-boot+swagger实现WebApi文档

    1.引用依赖包 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-s ...

  6. Performance — 前端性能监控利器

    Performance是一个做前端性能监控离不开的API,最好在页面完全加载完成之后再使用,因为很多值必须在页面完全加载之后才能得到.最简单的办法是在window.onload事件中读取各种数据. 大 ...

  7. PLSQL Developer windows 64位连接数据库的问题

    使用PLSQL Developer 工具连接到数据库进行开发,目前主流windows 系统都是64位操作系统,而PLSQL Developer  只有32位程序,所以在连接数据库上遇到一些问题. PL ...

  8. spring study

    Dependency Injection The Inversion of Control(IoC) is a general concept, and it can be expressed in ...

  9. Android里面安装windows系统

        安装前请确认以下条件:①:存储卡需要有大于302M的空间. 下载安装:1.下载文件并安装:①:下载地址:http://kuai.xunlei.com/d/hWIkAAIkJwAawgZUa3c ...

  10. 项目Beta冲刺团队随笔集

    博客集如下: Beta冲刺Day1:第一天冲刺记录 Beta冲刺Day2:第二天冲刺记录 Beta冲刺Day3:第三天冲刺记录 Beta冲刺Day4:第四天冲刺记录 Beta冲刺Day5:第五天冲刺记 ...