题目链接

题目翻译

  • 给定一张 \(n\) 个点 \(m\) 条边的无向图。
  • 一共有 \(k\) 种颜色,一开始,每条边都没有颜色。
  • 定义合法状态为仅保留染成 \(k\) 种颜色中的任何一种颜色的边,图都是一张二分图。
  • 有 \(q\) 次操作,第 \(i\) 次操作将第 \(e_i\) 条边的颜色染成 \(c_i\)。
  • 但并不是每次操作都会被执行,只有当执行后仍然合法,才会执行本次操作。
  • 你需要判断每次操作是否会被执行。
  • 数据范围:\(n,m,q \le 5 \times 10^5\),\(k \le 50\)。

    翻译出处

解题过程

首先二分图即保证图中不存在奇环,这可以用带权并查集或扩展域并查集实现,需要带一个\(\log\)

这题比较巧妙的是执行后仍然合法才会执行本次操作,看起来像强制在线,

其实不然,如果不合法直接将后面的边所染的颜色修改即可

由于修改染色比较困难,考虑线段树分治,那么仅仅需要可撤销并查集即可,由于有\(k\)种颜色,要开\(k\)个并查集

代码

#include <cstdio>
#include <cctype>
#include <vector>
#define rr register
using namespace std;
const int N = 1000011;
vector<int>K[N << 1];
int stad[N], tad[N], stac[N], tac[N], tot, tod;
int X[N], Y[N], U[N], V[N], cad[N], cac[N], last[N], Q, n, m, k;
inline void update(int rt, int l, int r, int x, int y, int z) {//在子区间内插入操作
if (l == x && r == y) {
K[rt].push_back(z);
return;
} rr int mid = (l + r) >> 1; if (y <= mid)
update(rt << 1, l, mid, x, y, z);
else if (x > mid)
update(rt << 1 | 1, mid + 1, r, x, y, z);
else
update(rt << 1, l, mid, x, mid, z), update(rt << 1 | 1, mid + 1, r, mid + 1, y, z);
}
struct Union_Set {
int f[N], dep[N];
inline signed getf(int u) {//求子树的祖先
return f[u] == u ? u : getf(f[u]);
}
inline void Merge(int col, int x, int y) {//合并两棵子树
rr int fa = getf(x), fb = getf(y); if (fa == fb)
return; if (dep[fa] > dep[fb])
fa ^= fb, fb ^= fa, fa ^= fb; if (dep[fa] == dep[fb]) {
stad[++tod] = fb, tad[tod] = dep[fb];
++dep[fb], cad[tod] = col;
} stac[++tot] = fa, tac[tot] = f[fa], f[fa] = fb, cac[tot] = col;
}
} T[51];
inline void dfs(int rt, int l, int r) {
rr int len = K[rt].size(), Tot = tot, Tod = tod; for (rr int i = 0; i < len; ++i) {
rr int t = K[rt][i];
T[V[t]].Merge(V[t], X[U[t]] + n, Y[U[t]]),
T[V[t]].Merge(V[t], X[U[t]], Y[U[t]] + n);
} rr int mid = (l + r) >> 1; if (l == r) {
rr int fa = T[V[l]].getf(X[U[l]]), fb = T[V[l]].getf(Y[U[l]]); if (fa == fb)
puts("NO"), V[l] = last[U[l]];//这条边直接改
else
puts("YES"), last[U[l]] = V[l];//更新边的颜色
} else
dfs(rt << 1, l, mid), dfs(rt << 1 | 1, mid + 1, r); for (; tot > Tot; --tot)//撤销操作
T[cac[tot]].f[stac[tot]] = tac[tot]; for (; tod > Tod; --tod)
T[cad[tod]].dep[stad[tod]] = tad[tod];
}
signed main() {
scanf("%d%d%d%d",&n,&m,&k,&Q);
for (rr int j = 1; j <= k; ++j)
for (rr int i = 1; i <= n * 2; ++i)
T[j].f[i] = i, T[j].dep[i] = 1; for (rr int i = 1; i <= m; ++i)
scanf("%d%d",&X[i],&Y[i]), last[i] = Q + 1; for (rr int i = 1; i <= Q; ++i)
U[i] = iut(), V[i] = iut(); for (rr int i = Q; i; --i) {
if (i < last[U[i]] - 1)
update(1, 1, Q, i + 1, last[U[i]] - 1, i);//注意i的位置只判定不修改 last[U[i]] = i;
} for (rr int i = 1; i <= m; ++i)
last[i] = 0; dfs(1, 1, Q);
return 0;
}

#扩展域并查集,线段树分治#CF576E Painting Edges的更多相关文章

  1. 【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)

    题目 CF576E 分析: 从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下. 首先做这题之前推荐一道很相似的题:[BZOJ4025]二分图(可撤销并查集+线段树 ...

  2. 【BZOJ4025】二分图(可撤销并查集+线段树分治)

    题目: BZOJ4025 分析: 定理:一个图是二分图的充要条件是不存在奇环. 先考虑一个弱化的问题:保证所有边出现的时间段不会交叉,只会包含或相离. 还是不会?再考虑一个更弱化的问题:边只会出现不会 ...

  3. 【离线 撤销并查集 线段树分治】bzoj1018: [SHOI2008]堵塞的交通traffic

    本题可化成更一般的问题:离线动态图询问连通性 当然可以利用它的特殊性质,采用在线线段树维护一些标记的方法 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常 ...

  4. [CSP-S模拟测试]:地理课(并查集+线段树分治)

    题目传送门(内部题146) 输入格式 从$geography.in$读入数据. 第一行两个数$n,m$,表示有$n$个点,$m$个时刻.接下来$m$行每行三个数,要么是$1\ u\ v$,要么是$2\ ...

  5. UVA1455 - Kingdom(并查集 + 线段树)

    UVA1455 - Kingdom(并查集 + 线段树) 题目链接 题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum ...

  6. 并查集&线段树&树状数组&排序二叉树

    超级无敌巨牛逼并查集(带权并查集)https://vjudge.net/problem/UVALive-4487 带删点的加权并查集 https://vjudge.net/problem/UVA-11 ...

  7. BZOJ 3910 并查集+线段树合并

    思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...

  8. 并查集 + 线段树 LA 4730 Kingdom

    题目传送门 题意:训练指南P248 分析:第一个操作可以用并查集实现,保存某集合的最小高度和最大高度以及城市个数.运用线段树成端更新来统计一个区间高度的个数,此时高度需要离散化.这题两种数据结构一起使 ...

  9. YYHS-猜数字(并查集/线段树维护)

    题目描述     LYK在玩猜数字游戏.    总共有n个互不相同的正整数,LYK每次猜一段区间的最小值.形如[li,ri]这段区间的数字的最小值一定等于xi.     我们总能构造出一种方案使得LY ...

  10. luogu5012 水の数列 (并查集+线段树)

    如果我们能求出来每个区间个数的最大分值,那就可以用线段树维护这个东西 然后出答案了 然后这个的求法和(luogu4269)Snow Boots G非常类似,就是我们把数大小排个序,每次都拿<=x ...

随机推荐

  1. CentOS6.8下yum安装Nginx

    在/etc/yum.repos.d/目录下创建一个源配置文件nginx.repo: cd /etc/yum.repos.d/ vim nginx.repo 填写如下内容: [nginx] name=n ...

  2. Finder Error code -36 “访达” 错误代码-36

    导致这个问题的原因是你的iCloud (iCloud和iCloud Drive是不一样的) 快满了. 如果你想解决这个问题,有以下三个方法: 1.多买苹果iCloud.(是的,苹果现在太恶心了.但这是 ...

  3. 【Azure 应用服务】在Azure上部署一套VUE框架的单页面应用,有什么可以参考的文档呢?

    问题描述 在Azure上部署一套VUE框架的单页面应用,有什么可以参考的文档呢? 问题回答 Azure官方上并没有VUE框架的实例代码,但是可以参考Node JS项目,来进行设置. 在 Azure 中 ...

  4. TCP和UDP可以使用同一个端口号吗?

    TCP和UDP可以使用同一个端口号吗? 首先说答案:可以.怎么理解呢? 我想这个问题要从计算机网络通信谈起,学过计算机网络的同学,可能都还记得7层或者4层网络模型,TCP/UDP属于其中的传输层协议, ...

  5. 在Linux下开启指定端口号

    1.查看某个端口是否已开启,如果提示no表示未开启 #8888表示要查询的端口号firewall-cmd --query-port=8888/tcp 2.永久开启端口号,提示 success 表示成功 ...

  6. 搭建一个Java项目可直接拿去使用的通用工具类

    1.通用枚举类 import lombok.Getter; /** * @Description 状态码定义约束,共6位数,前三位代表服务,后3位代表接口 * 比如 商品服务210,购物车是220.用 ...

  7. git拉项目, 1.新建目录 2 git clone 地址 . (重点最后的点)

  8. C#使用Stateless和箭头控件实现状态机的控制及显示

    之前开发一个小工具,内部实现一个状态机,并显示状态机当前状态及状态间的转移过程.我使用了Stateless开源类库及一个开源自定义箭头控件.自定义箭头控件是HZHControls其中一个控件,我单独把 ...

  9. Ubuntu 14.04傻瓜式安装 0@0

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  10. Android保存多张图片到本地

    目录介绍 01.实际开发保存图片遇到的问题 02.直接用http请求图片并保存本地 03.用glide下载图片保存本地 04.如何实现连续保存多张图片 05.关于其他介绍 好消息 博客笔记大汇总[16 ...