首页 > 其他分享 >CF576E 笔记

CF576E 笔记

时间:2024-03-08 13:00:48浏览次数:20  
标签:sz CF576E int 线段 笔记 st col void

前置知识:线段树分治。

题意

给定一个 \(n\) 个点 \(m\) 个点的图,有 \(k\) 种颜色,初始时每条边都没有颜色。

有 \(q\) 组询问,每组询问 \((i, c)\) 表示把第 \(i\) 条边颜色改成 \(c\),然后判断:所有颜色为 \(c\) 的边拉出来是否是一个二分图。

如果是就输出 YES;否则输出 NO,并撤销该操作。

\(n, m \le 5 \times 10^5, k \le 50\)

题解

考虑线段树分治。但是在线段树分治时,会有一个问题:无法确定一条边的出现时间。

思考一下线段树分治的性质,可以发现:当在线段树上递归到叶子结点,并处理当前叶子的询问时,前面的询问都被处理过了。就是说,遍历线段树,叶节点的询问一定是 \(1, 2, \cdots, q\) 的顺序被遍历。

于是,考虑同一条边被改的相邻的时间节点 \(x, y\),这条边会影响到的,只有 \([x + 1, y - 1]\) 中的询问。而递归到结点 \([l, r]\) ( \(x < l \le r < y\) ) 时,因为这个时候拿到的边的颜色是处理了 \([1, l - 1]\) 过后的,所以我们直接连边即可。总复杂度 \(O(n \log^2 n)\)。

代码

code:

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const int N = 1E6 + 5, K = 51;
int n, m, q, k, a[N], c[N], pre[N], nc[N];
pair <int, int> e[N];
stack <pair <pair <int, int>, int>> st;
struct bcj {
  int fa[N], sz[N];
  void init() {
    for (int i = 1; i <= 2 * n; ++i)
      fa[i] = i, sz[i] = 1;
  }
  int find(int x) {return x == fa[x] ? x : find(fa[x]);}
  void merge(int x, int y, int col) {
    x = find(x), y = find(y);
    if (x == y) return ;
    if (sz[x] > sz[y]) swap(x, y);
    st.emplace(make_pair(make_pair(x, y), col));
    fa[x] = y; sz[y] += sz[x];
  }
  void mer(int id, int col) {
    auto [x, y] = e[id];
    merge(x + n, y, col);
    merge(x, y + n, col);
  }
  void cut(int x, int y) {fa[x] = x; sz[y] -= sz[x];}
  bool same(int x, int y) {return find(x) == find(y);}
} f[K];
void cl(int to) {
  while ((int)st.size() > to) {
    auto [x, y] = st.top().first; int c = st.top().second; st.pop();
    f[c].cut(x, y);
  }
}
vector <int> v[N << 1];
void ins(int x, int l, int r, int L, int R, int p) {
  if (l >= L && r <= R) {
    v[x].emplace_back(p);
    return ;
  } int mid = (l + r) >> 1;
  if (L <= mid) ins(x << 1, l, mid, L, R, p);
  if (R > mid) ins(x << 1 | 1, mid + 1, r, L, R, p);
}
int wtf = 0;
void solve(int x, int l, int r) {
  int to = st.size();
  for (auto id : v[x]) {
    if (nc[id]) f[nc[id]].mer(id, nc[id]);
  }
  int mid = (l + r) >> 1;
  if (l == r) {
    int id = a[l]; auto [u, v] = e[id];
    if (f[c[l]].same(u, v)) cout << "NO\n";
    else cout << "YES\n", nc[id] = c[l];
  } else solve(x << 1, l, mid), solve(x << 1 | 1, mid + 1, r);
  cl(to);
}
signed main(void) {
  ios :: sync_with_stdio(false);
  cin.tie(nullptr); cout.tie(nullptr);
  cin >> n >> m >> k >> q;
  for (int i = 0; i <= k; ++i)
    f[i].init();
  for (int i = 1; i <= m; ++i)
    cin >> e[i].first >> e[i].second;
  for (int i = 1; i <= q; ++i) 
    cin >> a[i] >> c[i];
  for (int i = 1; i <= q; ++i) {
    if (pre[a[i]] + 1 <= i - 1)
      ins(1, 1, q, pre[a[i]] + 1, i - 1, a[i]);
    pre[a[i]] = i;
  } 
  for (int i = 1; i <= m; ++i)
    if (pre[i] < q) ins(1, 1, q, pre[i] + 1, q, i);
  solve(1, 1, q);
}

标签:sz,CF576E,int,线段,笔记,st,col,void
From: https://www.cnblogs.com/CTHOOH/p/18058627

相关文章

  • MYSQL学习笔记4: DML数据操作(增删改)
    DML数据操作(增删改)INSERT插入给指定字段插入数据insertinto表名(字段1,字段2...)values(值1,值2);向itcast的worker表的制定字段中插入一条新数据insertintoworkers(id,workNo,name,gender,age,idCard,entryDate)values(1,'1','hikari39','女',2......
  • MYSQL学习笔记3: DDL表修改
    DDL表修改在表中添加新字段#格式ALTERTABLE表名ADD字段名(长度)[COMMENT注释][约束];#在itcast表中新建一个nickname字段altertableitcastaddnicknamevarchar(20)comment'昵称';修改字段数据类型altertable表名modify字段名新数据类型(长度);修改字段名......
  • MYSQL学习笔记2: 数据类型
    数据类型数值类型TINYINTUNSIGNED无符号的tinyintDOUBLE(4,1)整体长度为4,小数位数为1的DOUBLE数据字符串类型CHAR(10)定长字符串,最多存储10个字符,占用10个字符的内存VARCHAR(10)变长字符串,最多存储10个字符,根据实际字符的长度计算内存空间对于CHAR和VARCHA......
  • Vue学习笔记40--脚手架项目架构分析
    脚手架项目架构分析1.babel.config.js——babel的控制文件,用于ES6转ES5(一般不需要程序员进行配置,如想研究请查看babel官网)module.exports={presets:['@vue/cli-plugin-babel/preset']}2.package.json——包信息说明,例如:项目名称、版本、采用的依赖、库文件......
  • (HASEE)神州笔记本 还原手册 —— 笔记本系统还原
    新买了一个笔记本,神州笔记本(HASEE),随机所带的手册,为防止丢失故把内容记录下来。开机时按:CTRL+H进入还原界面,点击“系统还原”,点击“恢复出厂备份”,确认。重启电脑后在“通用”方框内打钩,确认后再次重启。如何卸载/关闭该还原功能:开机按Ctrl+H,进入还原界面->......
  • 神州笔记本 —— HASEE神州 —— 用户手册(使用功能键)—— 笔记本电脑功能键
    功能键功能:FN+f1 启动/关闭触摸板FN+f2 启动/关闭屏幕背光FN+f3 启动/关闭喇叭和外接耳机FN+f5 减低音量FN+f6 提高音量FN+f7 切换屏幕FN+f8 降低屏幕亮度FN+f9 增加屏幕亮度FN+f10 启动/关闭摄像头FN+f11 启动/关闭飞行模式FN+f12 启动/关闭睡眠电源模式FN+~......
  • pandas笔记(三)-- 查找有效邮箱的用户(正则表达式应用)
    题目描述一个有效的电子邮件具有前缀名称和域,其中:前缀名称是一个字符串,可以包含字母(大写或小写),数字,'_','.',和破折号'—',前缀名必须以字母开头域名为'@leetcode.com'编写一个解决方案,以查找具有有效电子邮件的用户,以任何顺序返回结果表。测试用例输入us......
  • MYSQL学习笔记1: DDL的库表操作
    SQL语句分类DDL数据定义语言,用来定义数据库对象(数据库,表,字段)DML数据操作语言,用来对数据库中表的数据进行增删改DQL数据库查询语言,用于查询数据库中表的记录DCL数据控制语言,用来创建数据库用户、控制数据库的访问权限DDL数据定义语言,用来定义数据库对象(数据......
  • 技术笔记(4)MMORPG开发
    技术笔记(4)MMORPG开发希望实现的功能或目标:框架搭建UI系统‍学习笔记:Rules文件夹CanGetLayersExtensionCanSendCommandExtensionEventExtensionIBelongToArchitectureICanGetModelICanGetSystemICanGetUtilityICanRegistAndUnRegistEventICanSendCommand......
  • 读书笔记(2)《微精通》
    读书笔记(2)《微精通》背景:在学习如何有效读书的方法之后,想要更进一步的学习了解高效掌握一门技艺的方法。是的,还是带着无比功利性的目的挑选了这本书,希望能帮助自己在将来这段时间内充分利用全部精力和时间来稳步提升自我‍‍内容摘录:发觉兴趣+识别重心+立体学习+......