603E
LCT维护MST+子树信息
看了好长时间题解
editorial
结论:像做最小生成树一样,当每个连通块都是偶数个点就停下来。
每次复杂度mlogm
口胡
首先我们发现奇数个点是不满足每个点度数为奇数,因为一条边贡献两个度数,所以度数一定是偶数,但是奇数个点每个点奇数度度数总和是奇数,所以点数一定是偶数。
但是这样不足以解决问题。于是我们转化一下,如果一个连通块有偶数个点,那么这个连通块一定能满足条件。这里要注意,是满足条件,但是我们维护的东西并不满足条件。我们只维护最小生成森林,这样是不保证度数是奇数的,但是如果在森林上删去一些边,肯定能满足。既然多出来了一些边,怎么查找答案呢?我们每次加边,如果两个顶点不连通,那么我们连接,同时统计奇数个顶点的连通块,如果联通,那么我们删去形成的环上最大的边。然后把插入的边放进set里。每次查找,我们按边权从大到小检查,看这条边能否删去,能删去的条件是删掉这条边后两个连通块的点数都为偶数。删到不能删停下来。如果删掉一条边分裂成两个奇数大小的连通块,那么肯定是不满足条件的。这里就是解法的巧妙所在,我们保留一些可能没用的边,也不在乎性质,只有删边的时候才考虑。
然后还要维护子树信息。lct一般只能维护链上信息,但是我们发现,只有access和link和cut会改变子树之间的关系,那么我们就在这两个时候维护点权。(这里不是很清楚)
每次查询size的时候就把这个点转到根,查询即可。
好久没写lct都快忘了
#include<bits/stdc++.h>
using namespace std;
const int N = ;
struct edge {
int u, v, w, id;
edge(int u = , int v = , int w = , int id = ) : u(u), v(v), w(w), id(id) { }
bool operator < (edge e) const
{
return w == e.w ? id < e.id : w > e.w;
}
};
vector<edge> ed;
set<edge> s;
int n, m, o;
namespace lct
{
int top;
int fa[N], child[N][], size[N], v[N], tag[N], st[N], mx[N], id[N];
bool isroot(int x) { return !fa[x] || (child[fa[x]][] != x && child[fa[x]][] != x); }
void update(int x)
{
size[x] = size[child[x][]] + size[child[x][]] + v[x];
mx[x] = id[x];
if(ed[mx[child[x][]]].w > ed[mx[x]].w) mx[x] = mx[child[x][]];
if(ed[mx[child[x][]]].w > ed[mx[x]].w) mx[x] = mx[child[x][]];
}
void pushdown(int x)
{
if(!tag[x]) return;
tag[child[x][]] ^= ;
tag[child[x][]] ^= ;
swap(child[x][], child[x][]);
tag[x] ^= ;
}
void zig(int x)
{
int y = fa[x];
fa[x] = fa[y];
if(!isroot(y)) child[fa[x]][child[fa[x]][] == y] = x;
child[y][] = child[x][];
fa[child[x][]] = y;
fa[y] = x;
child[x][] = y;
update(y);
update(x);
}
void zag(int x)
{
int y = fa[x];
fa[x] = fa[y];
if(!isroot(y)) child[fa[x]][child[fa[x]][] == y] = x;
child[y][] = child[x][];
fa[child[x][]] = y;
fa[y] = x;
child[x][] = y;
update(y);
update(x);
}
void splay(int x)
{
top = ;
st[++top] = x;
for(int now = x; !isroot(now); now = fa[now]) st[++top] = fa[now];
for(int i = top; i; --i) pushdown(st[i]);
while(!isroot(x))
{
int y = fa[x], z = fa[y];
if(isroot(y))
{
child[y][] == x ? zig(x) : zag(x);
break;
}
else if(child[y][] == x && child[z][] == y) { zig(y); zig(x); }
else if(child[y][] == x && child[z][] == y) { zag(y); zag(x); }
else if(child[y][] == x && child[z][] == y) { zag(x); zig(x); }
else if(child[y][] == x && child[z][] == y) { zig(x); zag(x); }
}
}
void access(int x)
{
for(int y = ; x; y = x, x = fa[x])
{
splay(x);
v[x] -= size[y];
v[x] += size[child[x][]];
child[x][] = y;
update(x);
}
}
void rever(int x)
{
access(x);
splay(x);
tag[x] ^= ; //x本来是最深的,反转深度
}
void link(int x, int y)
{
rever(x);
fa[x] = y;
v[y] += size[x];
}
void cut(int x, int y)
{
rever(x); //u是最浅的
access(y);
splay(y);
fa[x] = child[y][] = ;
v[y] -= size[x];
update(y);
}
int find(int x)
{
access(x);
splay(x);
while(child[x][]) x = child[x][];
return x;
}
int q(int x)
{
rever(x);
return size[x];
}
} using namespace lct;
void add_edge(edge e)
{
if(q(e.u) & && q(e.v) & ) o -= ;
id[e.id + n] = e.id;
mx[e.id + n] = e.id;
link(e.u, e.id + n);
link(e.v, e.id + n);
}
int delete_edge(edge e)
{
cut(e.u, e.id + n);
cut(e.v, e.id + n);
if(q(e.u) & && q(e.v) & ) o += ;
return !(q(e.u) & );
}
int max_cost()
{
if(o) return -;
while(delete_edge(*s.begin())) s.erase(*s.begin());
add_edge(*s.begin());
return (*s.begin()).w;
}
int find_max(int u, int v)
{
rever(u);
access(v);
splay(v);
return mx[v];
}
void new_edge(edge e)
{
e.id = ed.size();
ed.push_back(e);
if(find(e.u) == find(e.v))
{
int id = find_max(e.u, e.v);
if(ed[id].w <= e.w) return;
delete_edge(ed[id]);
}
add_edge(e);
s.insert(e);
}
int main()
{
scanf("%d%d", &n, &m);
o = n;
ed.push_back(edge(, , , ));
for(int i = ; i <= n; ++i) v[i] = ;
for(int i = ; i <= m; ++i)
{
edge e;
scanf("%d%d%d", &e.u, &e.v, &e.w);
new_edge(e);
printf("%d\n", max_cost());
}
return ;
}
603E的更多相关文章
- Codeforces 603E Pastoral Oddities
传送门:http://codeforces.com/problemset/problem/603/E [题目大意] 给出$n$个点,$m$个操作,每个操作加入一条$(u, v)$长度为$l$的边. 对 ...
- [转帖]IBM POWER系列处理器的前世今生
IBM POWER系列处理器的前世今生 Power是Power Optimization With Enhanced RISC的缩写,是由IBM开发的一种RISC指令集架构(ISA). IBM的很多服 ...
- 转帖 IBM要推POWER9,来了解一下POWER处理器的前世今生
https://blog.csdn.net/kwame211/article/details/76669555 先来说一下最新的POWER 9 在Hot Chips会议上首次提到的IBM Power ...
- VINS(二)Feature Detection and Tracking
系统入口是feature_tracker_node.cpp文件中的main函数 1. 首先创建feature_tracker节点,从配置文件中读取信息(parameters.cpp),包括: ROS中 ...
- NOIP2017提高组 模拟赛13(总结)
NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...
随机推荐
- CSS——display:flex
Flex是Flexible Box的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性. 设为Flex布局以后,子元素的float.clear和vertical-align属性 ...
- 在python中调用js或者nodejs
在python中调用js或者nodejs要使用PyExecJs第三方包. pip install pyexecjs 示例代码 >>> import execjs >>&g ...
- jsTree使用记录
1. ajax请求生成jsTree <span style="font-size:14px;"><script> var r = []; // 权限树中被选 ...
- Python 之web动态服务器
webServer.py代码如下: import socket import sys from multiprocessing import Process class WSGIServer(obje ...
- SweetAlert弹出框
以前也用过,那个时候没有写过,突然看见了,就写上了. 网址:http://mishengqiang.com/sweetalert2/ swal({ title: '确定删除吗?', text: '你将 ...
- [如何在mac下使用gulp] 2. gulp模块的常用方法
常用的gulp模块方法有: gulp.src() gulp.src('client/one.js'); //指定明确的要处理文件 gulp.src('client/*.js'); //处理client ...
- Unity jointmoto
jointmoto是模拟电机的,他的参数包括了最高车速和最大扭矩 扭矩总是正数,而目标车速决定了方向
- 13.multi_match实现dis_max+tie_breaker
主要知识点: 基于multi_match语法实现dis_max+tie_breaker 1.best_fields+tie_breaker GET /forum/article/_search ...
- Django REST framework - 权限和限制
目录 Django REST framework 权限和限制 (你能干什么) 设置权限的方法 案例 第一步: 定义一个权限类 第二步: 使用 视图级别 全局级别设置 --- 限制 (你一分钟能干多少次 ...
- h5知识总结
移动开发基本知识点一. 使用rem作为单位 html { font-size: 100px; } @media(min-width: 320px) { html { font-size: 100px; ...