CF603E Pastoral Oddities 优先队列+结论+LCT维护生成树
首先,一个神奇的结论:
一个合法的方案存在的条件是每一个联通块的节点数都是偶数个的.
这个可以用数学归纳法简单证一证.
证出这个后,我们只需动态加入每一个边,并查看一下有哪些边能够被删除(删掉后联通块依然合法).
对于维护加边,删边,我们用动态树.
对于枚举哪些边可以被删,我们可以用堆/set来维护.
由于每一条边最多只会加一次,也最多只会删一次,所以总时间复杂度为 $O(nlogm)$.
- #include <cstdio>
- #include <queue>
- #include <cstring>
- #include <algorithm>
- #define lson t[x].ch[0]
- #define rson t[x].ch[1]
- #define N 500000
- #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
- using namespace std;
- struct Edge {
- int u,v,c,id;
- Edge(int u=0,int v=0,int c=0,int id=0):u(u),v(v),c(c),id(id){}
- bool operator<(Edge a) const{
- return a.c>c;
- }
- }e[N];
- priority_queue<Edge>q;
- int sta[N],n,m,del[N];
- struct Node {
- int ch[2],max,val,son,size,f,id,rev;
- }t[N];
- int isrt(int x) {
- return !(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x);
- }
- int get(int x) {
- return t[t[x].f].ch[1]==x;
- }
- void mark(int x) {
- if(!x) return;
- swap(lson,rson), t[x].rev^=1;
- }
- void pushup(int x) {
- t[x].max=t[x].val,t[x].id=x;
- t[x].max=max(t[x].max,max(t[lson].max,t[rson].max));
- if(t[lson].max==t[x].max) t[x].id=t[lson].id;
- if(t[rson].max==t[x].max) t[x].id=t[rson].id;
- t[x].size=t[x].son+t[lson].size+t[rson].size+(x<=n);
- }
- void pushdown(int x) {
- if(t[x].rev) mark(lson), mark(rson), t[x].rev=0;
- }
- void rotate(int x) {
- int old=t[x].f,fold=t[old].f,which=get(x);
- if(!isrt(old))
- t[fold].ch[t[fold].ch[1]==old]=x;
- t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old;
- t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold;
- pushup(old),pushup(x);
- }
- void splay(int x) {
- int v=0,u=x,fa;
- for(sta[++v]=u;!isrt(u);u=t[u].f) sta[++v]=t[u].f;
- for(int i=v;i>=1;--i) pushdown(sta[i]);
- for(u=t[u].f;(fa=t[x].f)!=u;rotate(x))
- if(t[fa].f!=u)
- rotate(get(fa)==get(x)?fa:x);
- }
- void Access(int x) {
- int y=0;
- while(x) {
- splay(x);
- t[x].son-=t[y].size;
- t[x].son+=t[rson].size;
- rson=y,pushup(x),y=x,x=t[x].f;
- }
- }
- void makeroot(int x) {
- Access(x),splay(x),mark(x);
- }
- int findroot(int x) {
- int u;
- Access(x),splay(x);
- while(x) {
- pushdown(x);
- u=x,x=lson;
- }
- return u;
- }
- void split(int x,int y) {
- makeroot(x),Access(y),splay(y);
- }
- void link(int x,int y) {
- makeroot(x), makeroot(y),t[x].f=y, t[y].son+=t[x].size,pushup(y);
- }
- void cut(int x,int y) {
- makeroot(x),Access(y),splay(y);
- t[y].ch[0]=t[x].f=0;
- pushup(y);
- }
- int main() {
- int i,j;
- // setIO("input");
- scanf("%d%d",&n,&m);
- if(n%2==1) {
- for(i=1;i<=m;++i) printf("-1\n");
- return 0;
- }
- int cnt=n;
- for(i=1;i<=m;++i) {
- int u,v,c;
- scanf("%d%d%d",&u,&v,&c);
- e[i]=Edge(u,v,c,i+n);
- int x=findroot(u),y=findroot(v);
- if(x!=y) {
- int now=i+n;
- makeroot(u),makeroot(v);
- if(t[u].size%2==1&&t[v].size%2==1) cnt-=2;
- t[now].val=c;
- link(u,now),link(now,v);
- q.push(Edge(u,v,c,now));
- }
- else {
- split(u,v);
- if(t[v].max>c) {
- int cc=t[v].id,xx=e[cc-n].u,yy=e[cc-n].v,now=i+n;
- cut(cc,xx),cut(cc,yy), t[now].val=c;
- del[cc]=1;
- link(u,now),link(now,v);
- q.push(Edge(u,v,c,now));
- }
- }
- if(cnt) printf("-1\n");
- else {
- while(1) {
- while(!q.empty()&&del[q.top().id]) q.pop();
- int xx=q.top().u,yy=q.top().v,cc=q.top().id,X,Y;
- makeroot(cc);
- Access(xx),splay(xx),X=t[xx].size-t[cc].size;
- Access(yy),splay(yy),Y=t[yy].size-t[cc].size;
- if(X%2==0&&Y%2==0)
- cut(xx,cc),cut(yy,cc),q.pop();
- else break;
- }
- printf("%d\n",q.top().c);
- }
- }
- return 0;
- }
CF603E Pastoral Oddities 优先队列+结论+LCT维护生成树的更多相关文章
- CF603E Pastoral Oddities
CF603E Pastoral Oddities 度数不好处理.转化题意:不存在连通块为奇数时候就成功了(自底向上调整法证明) 暴力:从小到大排序加入.并查集维护.全局变量记录奇数连通块的个数 答案单 ...
- 洛谷4234最小差值生成树 (LCT维护生成树)
这也是一道LCT维护生成树的题. 那么我们还是按照套路,先对边进行排序,然后顺次加入. 不过和别的题有所不同的是: 在本题中,我们需要保证LCT中正好有\(n-1\)条边的时候,才能更新\(ans\) ...
- Vijos1865 NOI2014 魔法森林 LCT维护生成树
基本思路: 首先按照weightA升序排序,然后依次在图中加边,并维护起点到终点路径上weightB的最大值 如果加边过程中生成了环,则删除环中weightB最大的边 由于是无向图,点之间没有拓扑序, ...
- 【CF603E】Pastoral Oddities cdq分治+并查集
[CF603E]Pastoral Oddities 题意:有n个点,依次加入m条边权为$l_i$的无向边,每次加入后询问:当前图是否存在一个生成子图,满足所有点的度数都是奇数.如果有,输出这个生成子图 ...
- LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治
题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ...
- bzoj 4736: 温暖会指引我们前行 (LCT 维护最大生成树)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4736 题面: 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出 ...
- BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT维护最大生成树 主席树
题面 考虑没有询问,直接给你一个图问联通块怎么做. 并查集是吧. 现在想要动态地做,那么应该要用LCT. 考虑新加进来一条边,想要让它能够减少一个联通块的条件就是现在边的两个端点还没有联通. 如果联通 ...
- Codeforces603E - Pastoral Oddities
Portal Description 初始时有\(n(n\leq10^5)\)个孤立的点,依次向图中加入\(m(m\leq3\times10^5)\)条带权无向边.使得图中每个点的度数均为奇数的边集是 ...
- Codeforces 603E Pastoral Oddities
传送门:http://codeforces.com/problemset/problem/603/E [题目大意] 给出$n$个点,$m$个操作,每个操作加入一条$(u, v)$长度为$l$的边. 对 ...
随机推荐
- RPC基本原理
RPC非常重要,很多人面试的时候都挂在了这个地方!你要是还不懂RPC是什么?他的基本原理是什么?你一定要把下边的内容记起来!好好研究一下!特别是文中给出的一张关于RPC的基本流程图,重点中的重点,Du ...
- sql server查询数据库连接数
设置最大连接数 下面的T-SQL 语句可以配置SQL Server 允许的并发用户连接的最大数目. exec sp_configure 'show advanced options', 1exec s ...
- Python环境配置问题及解决办法
Windows下用pip安装包时出现"error: Microsoft Visual C++ 9.0 is required"错误 error: Microsoft Visual ...
- Luogu P4118 [Ynoi2016]炸脖龙I
题目 首先考虑没有修改的情况.显然直接暴力扩展欧拉定理就行了,单次复杂度为\(O(\log p)\)的. 现在有了修改,我们可以树状数组维护差分数组,然后\(O(\log n)\)地单次查询单点值. ...
- 如何用纯 CSS 创作一个精彩的彩虹 loading 特效
效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/vjvoow 可交互视频教 ...
- 配置Mysql远程连接
一.赋予某个用户权限 1.赋予权限格式:grant 权限 on 数据库对象 to 用户@IP(或者相应正则) 注:可以赋予select,delete,update,insert,index等权限精确到 ...
- css中的position 的absolute和relative的区别(转)
我们先来看看CSS3 Api中对position属性的相关定义: static:无特殊定位,对象遵循正常文档流.top,right,bottom,left等属性不会被应用. relative:对象遵循 ...
- 阿里云服务器配置https
第一步 在阿里云控制台找到申请ssl证书的地址(我申请的是阿里云免费的证书,申请完要等申请通过,可能要等待一两天) 第二步下载ssl nginx版本的证书 第三步上传证书(包含.key, .pem这两 ...
- 好用的 python 工具集合
图标处理小程序, 妈妈再也不用担心我不会制作图标了 # PythonMargick包可以到Unofficial Windows Binaries for Python Extension Packag ...
- django优化--ORM查询
ORM提供了两个方法用来优化查询效率 1. select_related 有两张表:表结构如下: class Scheme(models.Model): """ 套餐类 ...