【CF603E】Pastoral Oddities

题意:有n个点,依次加入m条边权为$l_i$的无向边,每次加入后询问:当前图是否存在一个生成子图,满足所有点的度数都是奇数。如果有,输出这个生成子图中边权最大的边的权值最小可能是多少。

$n\le 10^5,m\le 10^6,l_i\le 10^9$

题解:可以证明如果存在一个生成子图满足所有点度数都是奇数,当且仅当所有连通块都有偶数个点。并且可以知道加边一定不会使答案更劣。正解有三种:1.LCT维护最小生成树;2.cdq分治(类似整体二分);3.线段树(类似按时间分治)。都比较神,本人采用了第二种。

官方题解:http://codeforces.com/blog/entry/21914

大神的第二种做法的题解:https://www.cnblogs.com/galaxies/p/cf603E.html

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. using namespace std;
  6. const int maxn=100010;
  7. const int maxm=300010;
  8. int f[maxn],g[maxn],siz[maxn],st[maxn],ans[maxm];
  9. int n,m,cnt,top;
  10. struct edge
  11. {
  12. int a,b,c,tim;
  13. }p[maxm],q[maxm];
  14. bool cmp(const edge &a,const edge &b)
  15. {
  16. return (a.c==b.c)?(a.tim<b.tim):(a.c<b.c);
  17. }
  18. inline void uni(int a,int b)
  19. {
  20. int x=a,y=b,c=0,d=0;
  21. while(f[x]!=x) x=f[x],c++;
  22. while(f[y]!=y) y=f[y],d++;
  23. if(x==y) return ;
  24. if(c>d) swap(x,y),swap(a,b);
  25. cnt-=(siz[x]&1)+(siz[y]&1)-((siz[x]+siz[y])&1);
  26. siz[y]+=siz[x],f[x]=y;
  27. st[++top]=x;
  28. }
  29. inline void del(int x)
  30. {
  31. int y=f[x];
  32. siz[y]-=siz[x],f[x]=x;
  33. cnt+=(siz[x]&1)+(siz[y]&1)-((siz[x]+siz[y])&1);
  34. }
  35. void solve(int l,int r,int L,int R)
  36. {
  37. if(l>r) return ;
  38. int mid=(l+r)>>1,i,now=top,MID;
  39. for(i=l;i<=mid;i++) if(p[i].c<=L) uni(p[i].a,p[i].b);
  40. for(i=L;i<=R&&cnt;i++) if(q[i].tim<=mid) uni(q[i].a,q[i].b);
  41. MID=max(L,i-1);
  42. if(!cnt) ans[p[mid].tim]=q[MID].c;
  43. else ans[p[mid].tim]=-1;
  44. while(top>now) del(st[top--]);
  45. for(i=L;i<=MID;i++) if(q[i].tim<=l) uni(q[i].a,q[i].b);
  46. solve(l,mid-1,MID,R);
  47. while(top>now) del(st[top--]);
  48. for(i=l;i<=mid;i++) if(p[i].c<=L) uni(p[i].a,p[i].b);
  49. solve(mid+1,r,L,MID);
  50. while(top>now) del(st[top--]);
  51. }
  52. inline int rd()
  53. {
  54. int ret=0,f=1; char gc=getchar();
  55. while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
  56. while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
  57. return ret*f;
  58. }
  59. int main()
  60. {
  61. n=rd(),m=rd();
  62. int i;
  63. for(i=1;i<=m;i++) p[i].a=rd(),p[i].b=rd(),p[i].c=rd(),p[i].tim=i,q[i]=p[i];
  64. sort(q+1,q+m+1,cmp);
  65. for(i=1;i<=n;i++) f[i]=i,siz[i]=1;
  66. for(i=1;i<=m;i++) p[q[i].tim].c=i;
  67. cnt=n;
  68. solve(1,m,1,m);
  69. for(i=1;i<=m;i++) printf("%d\n",ans[i]);
  70. return 0;
  71. }

【CF603E】Pastoral Oddities cdq分治+并查集的更多相关文章

  1. 【openjudge】C15C Rabbit's Festival CDQ分治+并查集

    题目链接:http://poj.openjudge.cn/practice/C15C/ 题意:n 点 m 边 k 天.每条边在某一天会消失(仅仅那一天消失).问每一天有多少对点可以相互到达. 解法:开 ...

  2. hdu_5354_Bipartite Graph(cdq分治+并查集判二分图)

    题目链接:hdu_5354_Bipartite Graph 题意: 给你一个由无向边连接的图,问对于每一个点来说,如果删除这个点,剩下的点能不能构成一个二分图. 题解: 如果每次排除一个点然后去DFS ...

  3. BZOJ 4025: 二分图 [线段树CDQ分治 并查集]

    4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...

  4. 2018.10.01 bzoj3237: [Ahoi2013]连通图(cdq分治+并查集)

    传送门 cdq分治好题. 对于一条边,如果加上它刚好连通的话,那么删掉它会有两个大集合A,B.于是我们先将B中禁用的边连上,把A中禁用的边禁用,再递归处理A:然后把A中禁用的边连上,把B中禁用的边禁用 ...

  5. [HDU5354]Bipartite Graph(CDQ分治+并查集)

    经典动态二分图问题. 考虑solve(l,r)分治成l,mid和mid+1,r.先将区间[mid+1,r]中的点全部加入图中,若此时存在奇环则ans[l..mid]全部为0,否则递归到左边. 递归完左 ...

  6. CF603E Pastoral Oddities

    CF603E Pastoral Oddities 度数不好处理.转化题意:不存在连通块为奇数时候就成功了(自底向上调整法证明) 暴力:从小到大排序加入.并查集维护.全局变量记录奇数连通块的个数 答案单 ...

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

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

  8. 2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:h ...

  9. 【CF576E】Painting Edges 线段树按时间分治+并查集

    [CF576E]Painting Edges 题意:给你一张n个点,m条边的无向图,每条边是k种颜色中的一种,满足所有颜色相同的边内部形成一个二分图.有q个询问,每次询问给出a,b代表将编号为a的边染 ...

随机推荐

  1. ABBYY FineReader 14助力2017,正式进入新纪元

    ABBYY FineReader 12自2014年推出以来,已经给万千用户的工作带来了便捷,蝉联优秀殊荣这么久,相信不少用户早在期待新版本的到来了吧.这不,ABBYY FineReader 14问世了 ...

  2. QT编译错误: multiple definition of `qMain(int, char**)'

    QT使用过程中来回添加修改代码,结果出现了编译错误:error: multiple definition of `qMain(int, char**)' 一直看我的源文件是都哪里有错误,最后发现是在p ...

  3. 更改mysql的加密方式和密码策略

    -- 修改密码为用不过期 mysql> ALTER USER 'root'@'%' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; Query O ...

  4. 变分推断(Variational Inference)

    (学习这部分内容大约需要花费1.1小时) 摘要 在我们感兴趣的大多数概率模型中, 计算后验边际或准确计算归一化常数都是很困难的. 变分推断(variational inference)是一个近似计算这 ...

  5. mongodb 初学 索引

    连接服务器异常(Connection refused) 啦啦啦 mongodb 搭建主从服务器 啦啦啦 Mongodb启动命令mongod参数说明 啦啦啦 MongoDB 分片 啦啦啦 啦啦啦 啦啦啦 ...

  6. Linux 集群架构

    集群介绍 Keepalived 配置高可用集群

  7. Splash Lua 脚本

    Splash 可以通过 Lua 脚本执行一系列渲染操作,这样我们就可以用 Splash 来模拟浏览器的操作了,Splash Lua 基础语法如下: function main(splash, args ...

  8. Ansible的快速入门

    Ansible 是一个简单的自动化引擎,可完成配置管理,应用部署,服务编排等各种IT需求. Ansible使用python语言开发实现的开源软件,依赖于Jinjia2,paramiko和PyYAML这 ...

  9. [Ubuntu] APT - Advanced Packaging Tool 简明指南

    Advanced Packaging Tool,一般简称为apt,是Debian GNU/Linux distribution及其变体版本中与核心库一道处理软件的安装和卸载. Ubuntu是Debia ...

  10. 重写MFC窗口上的关闭按钮事件(SDI, MDI, Dialog)

    This piece of code demonstrate how to override WM_CLOSE event. 点击窗口关闭按钮,触发相关事件! 有时候,在MFC程序退出之前,我们通常会 ...