题目

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();
}

【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. bzoj 3237 连通图 - 并查集 - 线段树

    Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connected Disconne ...

  8. 【xsy2506】 bipartite 并查集+线段树

    题目大意:有$n$个点,你需要操作$m$次.每次操作为加入/删除一条边. 问你每次操作后,这$n$个点构成的图是否是二分图. 数据范围:$n,m≤10^5$. 此题并没有强制在线,考虑离线做法. 一条 ...

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

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

随机推荐

  1. LINUX-文件的权限 - 使用 "+" 设置权限,使用 "-" 用于取消

    ls -lh 显示权限 ls /tmp | pr -T5 -W$COLUMNS 将终端划分成5栏显示 chmod ugo+rwx directory1 设置目录的所有人(u).群组(g)以及其他人(o ...

  2. circumferential averaged streamwise velocity in ParaView

    Goal: get a averaged axial velocity in a circular loop (dashed line in the following figure) Steps: ...

  3. java Beanutils.copyProperties( )用法

    这是一篇开发自辩甩锅稿~~~~ 昨天测试小姐姐将我的一个bug单重开了,emmmm....内心OS:就调整下对象某个属性类型这么简单的操作,我怎么可能会出错呢,一定不是我的锅!!but再怎么抗拒,bu ...

  4. npm安装node包时怎么显示安装进度

    npm config set loglevel=http 打开这个你会看到所有的 HTTP 请求,除此之外如果还有 \ 长时间打转,那就是外部模块的编译过程,一个字:等. 具体地址可参考https:/ ...

  5. [luoguP3052] [USACO12MAR]摩天大楼里的奶牛Cows in a Skyscraper(DP)

    传送门 输出被阉割了. 只输出最少分的组数即可. f 数组为结构体 f[S].cnt 表示集合 S 最少的分组数 f[S].v 表示集合 S 最少分组数下当前组所用的最少容量 f[S] = min(f ...

  6. sdibt 1251 进化树问题

    /* 三个点的话 A--D--B | C dis(AD)=(AB+AC-BC)/2; 拓展到到n个点 每次去叶子节点,先去掉与A相连长度最小的. 将他们的长度加起来. */ #include<s ...

  7. 单例模式解决RabbitMQ超出最大连接问题

    今天在项目稳定性测试过程中遇到一个情景:通过工具jMeter一直请求消息转发服务器,消息转发服务器再向rabbitMQ发送数据,在这期间出现了问题.MQ意外宕机. 1. 查看rabbitMQ管理界面. ...

  8. [Vue-rx] Share RxJS Streams to Avoid Multiple Requests in Vue.js

    Splitting a stream into multiple streams causes new subscriptions. You can think of new subscription ...

  9. varnish代理server笔记

    varnish是一款开源的代理server软件.和Squid的差别是採用内存进行数据缓存. 速度很的快,并且不easy崩溃.可是奔溃之后全部数据都消失,导致全部请求全部发送至后台server端,这是其 ...

  10. C#趣味程序---九九乘法表

    using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { for ...