题目链接

题目翻译

  • 给定一张 \(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. 2021-10-25 css中零值0后面是否要省略单位

    原理 在css中如果值为0,可以省略单位. 在css应用场景中,有可能是多端多人维护.即可能维护的人有A及B及C-,应用场景中有电脑端及手机端及小程序及打印机之类的. 结论 个人认为不要省略单位,不要 ...

  2. Vue框架设计:性能权衡的艺术

    "框架设计里到处都体现了权衡的艺术." 当我们设计一个框架的时候,框架本身的各个模块之间并不是相互独立的,而是相互关联.相互制约的.因此作为框架设计者,一定要对框架的定位和方向拥有 ...

  3. 矩池云如何自定义端口,访问自己的web项目

    本文将给您介绍如何在矩池云租用服务器的时候自定义端口,并将您的 web 项目部署到自定义端口,最后实现在本地通过自定义端口对应链接访问服务. 上传代码和数据 首先,您需要将本地的项目代码和数据上传到矩 ...

  4. 【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数

    问题描述 在Azure App Service for Windows的环境中,部署.NET应用,其中使用了 SAP NetWeaver RFC函数 (需要加载 sapnwrfc.dll).详细的错误 ...

  5. 【Azure 事件中心】使用Apache Flink 连接 Event Hubs 出错 Kafka error: No resolvable bootstrap urls

    问题描述 参考Github上 Event Hub的示例代码(Using Apache Flink with Event Hubs for Apache Kafka Ecosystems : https ...

  6. spark 下java list 或者scala list 转DataFrame or DataSet 总结

    一.JAVA list 转 DataFrame or DataSet case class CaseJava( var num: String, var id: String, var start_t ...

  7. C++ auto与循环

    C++ auto与循环 C++ auto 的介绍 typeid(p).name();可以输出auto的类型 auto 是 C++11 引入的一个关键字,用于自动类型推导.编译器会根据初始化表达式的类型 ...

  8. Java 交换两个变量的值

    1 //交换两个变量的值 2 // 1 3 int nu1 = 10; 4 int nu2 = 20; 5 6 System.out.println("nu1 = "+nu1+&q ...

  9. IDEA使用与多线程

    IDEA缩写和快捷键 psvm全称public static void main sout 全称public static void main alt+enter 处理异常 s.out 自动打印s c ...

  10. 第12章_MySQL数据类型精讲

    第12章_MySQL数据类型精讲 讲师:尚硅谷-宋红康(江湖人称:康师傅) 官网:http://www.atguigu.com 1. MySQL中的数据类型 类型 类型举例 整数类型 TINYINT. ...