题目

CF576E

分析:

从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下。

首先做这题之前推荐一道很相似的题:【BZOJ4025】二分图(可撤销并查集+线段树分治)

大力每个颜色维护一个并查集,就很像上面那道题了。但是存在一个问题:在处理线段树区间\([l,r]\)时,可能并不知道\(l\)处的修改是否成功,所以不知道\(l\)处修改的边具体是什么颜色的。

我的解决方案是:处理区间\([l,r]\)时忽略\(l\)处修改的边。先向左子树递归,递归到叶子时判断本次修改颜色能否成功。然后回溯后向右子树递归前将这条边加入。

代码:

solve函数的第四个参数表示现在是否已经忽略了\(l\)处修改的边。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <queue>
#include <bitset>
#include <stack> using namespace std; namespace zyt
{
template<typename T>
inline void read(T &x)
{
char c;
bool f = false;
x = 0;
do
c = getchar();
while (c != '-' && !isdigit(c));
if (c == '-')
f = true, c = getchar();
do
x = x * 10 + c - '0', c = getchar();
while (isdigit(c));
if (f)
x = -x;
}
template<typename T>
inline void write(T x)
{
static char buf[20];
char *pos = buf;
if (x < 0)
putchar('-'), x = -x;
do
*pos++ = x % 10 + '0';
while (x /= 10);
while (pos > buf)
putchar(*--pos);
}
inline void write(const char *const s)
{
printf("%s", s);
}
const int N = 5e5 + 10, B = 19, K = 51;
int n, m, k, q, head[1 << (B + 1) | 11], ecnt;
struct UFS
{
int fa[N], rk[N];
bitset<N> dis;
struct node
{
UFS &ufs;
int x, y, fa, rk, dis;
};
static stack<node> sta;
inline void init()
{
for (int i = 0; i < N; i++)
fa[i] = i, rk[i] = 1;
dis = 0U;
}
int f(const int x)
{
return x == fa[x] ? x : f(fa[x]);
}
int dist(const int x)
{
return x == fa[x] ? dis[x] : dist(fa[x]) ^ dis[x];
}
inline bool merge(const int u, const int v)
{
int x = f(u), y = f(v);
if (x == y)
return dist(u) ^ dist(v);
if (rk[x] > rk[y])
swap(x, y);
sta.push((node){*this, x, y, fa[x], rk[y], dis[x]});
fa[x] = y, dis[x] = dis[x] ^ dist(u) ^ dist(v) ^ 1;
if (rk[x] == rk[y])
++rk[y];
return true;
}
static inline int set_undo()
{
return sta.size();
}
static inline void undo(const int bck)
{
while (sta.size() > bck)
{
UFS &now = sta.top().ufs;
now.fa[sta.top().x] = sta.top().fa;
now.rk[sta.top().y] = sta.top().rk;
now.dis[sta.top().x] = sta.top().dis;
sta.pop();
}
}
}ufs[K];
stack<UFS::node> UFS::sta;
struct edge
{
int id, next;
}e[N * B];
inline void add(const int a, const int b)
{
e[ecnt] = (edge){b, head[a]}, head[a] = ecnt++;
}
struct ed
{
int u, v;
}arr[N];
struct node
{
int ed, col;
}mdf[N];
int pre[N], nxt[N], last[N];
namespace Segment_Tree
{
void insert(const int rot, const int lt, const int rt, const int ls, const int rs, const int id)
{
if (ls <= lt && rt <= rs)
{
add(rot, id);
return;
}
int mid = (lt + rt) >> 1;
if (ls <= mid)
insert(rot << 1, lt, mid, ls, rs, id);
if (rs > mid)
insert(rot << 1 | 1, mid + 1, rt, ls, rs, id);
}
void solve(const int rot, const int lt, const int rt, bool flag)
{
int mid = (lt + rt) >> 1;
int bck = UFS::set_undo();
bool f = false;
for (int i = head[rot]; ~i; i = e[i].next)
{
int now = e[i].id;
if (lt == now)
{
flag = true;
continue;
}
UFS &u = ufs[mdf[now].col];
ed &edg = arr[mdf[now].ed];
if (mdf[now].col)
u.merge(edg.u, edg.v);
}
if (lt == rt)
{
if (!ufs[mdf[lt].col].merge(arr[mdf[lt].ed].u, arr[mdf[lt].ed].v))
mdf[lt].col = mdf[pre[lt]].col, write("NO");
else
write("YES");
putchar('\n');
}
else
{
solve(rot << 1, lt, mid, f | flag);
if (f | flag)
ufs[mdf[lt].col].merge(arr[mdf[lt].ed].u, arr[mdf[lt].ed].v);
solve(rot << 1 | 1, mid + 1, rt, false);
}
UFS::undo(bck);
}
}
int work()
{
using namespace Segment_Tree;
memset(head, -1, sizeof(head));
read(n), read(m), read(k), read(q);
for (int i = 1; i <= k; i++)
ufs[i].init();
for (int i = 1; i <= m; i++)
read(arr[i].u), read(arr[i].v);
for (int i = 1; i <= q; i++)
{
read(mdf[i].ed), read(mdf[i].col);
nxt[i] = q + 1;
}
for (int i = 1; i <= q; i++)
{
if (last[mdf[i].ed])
pre[i] = last[mdf[i].ed];
last[mdf[i].ed] = i;
}
for (int i = q; i > 0; i--)
nxt[pre[i]] = i;
for (int i = 1; i <= q; i++)
insert(1, 1, q, i, nxt[i] - 1, i);
solve(1, 1, q, false);
return 0;
}
}
int main()
{
return zyt::work();
}

最新文章

  1. php工作笔记4-mysql笔记1
  2. 对于Access数据库查询遇到空值的解决办法
  3. KVM虚拟机网络基础及优化说明
  4. oracle imp导入库到指定表空间
  5. 【BZOJ 1007】 [HNOI2008]水平可见直线
  6. YUV格式详解
  7. 利用js闭包获取索引号
  8. js动态创建样式: style 和 link
  9. 转:JMeter进行Java 请求测试
  10. loadrunner:Auto Correlate自动定位瓶颈
  11. Java计算字符串中字母出现的次数
  12. 强大的API测试工具Hitchhiker v0.9 基于UI的断言测试,回顾2017
  13. &quot;未找到应用程序的“aps-environment”的权利字符串&quot;
  14. 【c#】RabbitMQ学习文档(三)Publish/Subscribe(发布/订阅)
  15. 关于MySQL数据库——增删改查语句集锦
  16. 关于vue项目去除margin和padding后设置元素width和height为100%后,出现滚动条问题(移动端)
  17. RPC远程过程调用实例
  18. 潭州课堂25班:Ph201805201 django 项目 第二十四课 文章主页 多级评论数据库设计 ,后台代码完成 (课堂笔记)
  19. int**a = new int[5][6] 怎么delete
  20. Matlab arenstorf problem

热门文章

  1. day21 02 包的进阶
  2. outflow Boundary Condition in FLuent
  3. SecureCRT 8.0设置与使用
  4. 【OpenCV, MFC】利用MFC和OpenCV通过系统对话框打开和保存图片
  5. Codeforces Round #228 (Div. 2)
  6. Windows中更新python模块的命令
  7. vim配置说明20170819
  8. Hackerrank manasa-and-combinatorics(数学推导)
  9. Java设计模式补充:回调模式、事件监听器模式、观察者模式(转)
  10. Node &amp; Express: some tips