题目链接:点击查看

题目大意:给出 nnn 个点,初始时互相不存在连边,需要执行 mmm 次操作,每次操作分为两种类型:

  1. 1xy1 \ x \ y1 x y:如果 (x,y)(x,y)(x,y) 之间没有连边,则增加连边;如果 (x,y)(x,y)(x,y) 之间存在连边,则删除连边
  2. 2xy2 \ x \ y2 x y:询问点 xxx 和点 yyy 之间是否联通

询问需要强制在线

题目分析:关于强制在线实现连边与加边,如果是在树上进行的话可以用 LCTLCTLCT,但如果放在图上的话好像是可以用 ETTETTETT,不过这个题目需要看出这个强制在线是个假的,所以可以离线去做

之前做过一道类似的题目:牛客多校8 - All-Star Game

所以这个题目考虑用线段树分治离线去做,将每个节点视为询问的时间点,递归的时候实现并查集的加边,回溯的时候实现并查集的撤销即可,访问到叶子节点时回答每个询问并且更新后续的询问

然后关键点就是如何将题目转换成离线去做,因为上一次的答案只可能为 000 或 111,所以对于一对询问 (x,y)(x,y)(x,y) 来说,只可能是 (x,y)(x,y)(x,y) 或 (xmodn+1,ymodn+1)(x \bmod n+1,y\bmod n+1)(xmodn+1,ymodn+1),对于操作二的话无伤大雅,直接存起来下面会讲如何更新,而对于操作一来说,线段树分治的本质就是将 (x,y)(x,y)(x,y) 这条边的出现时间删除时间的这段区间打上标记,所以我们可以在读入时就将所有的 (x,y)(x,y)(x,y) 点对都压入到线段树中

举个很简单的例子,假设 (x,y)(x,y)(x,y) 这条边的出现位置共有三次,分别是 t1,t2,t3t_1,t_2,t_3t1​,t2​,t3​,我们先不用管哪个时间点是删除,哪个时间点是增加,直接将所有的连续区间都打上标记,诸如:[t1,t2],[t2,t3],[t3,m][t_1,t_2],[t_2,t_3],[t_3,m][t1​,t2​],[t2​,t3​],[t3​,m]( mmm 是询问的个数,相当于最后的一个时间点),然后在分治的过程中,根据实际的询问去选择是否加边

最后说一下如何实时更新出实际的询问以及加边,因为线段树递归到叶子节点的顺序一定是从左到右下去的,所以当递归到叶子节点 xxx 时,x−1x-1x−1 一定结束了,且 x+1x+1x+1 一定还没有被访问过,利用这个特点每次询问完叶子节点 xxx 后可以顺便将 x+1x+1x+1 位置的询问更新一下

代码:

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f;
}
template<typename T>
inline void write(T x)
{if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=2e5+100;
struct{int op,x,y;}q[N];
map<pair<int,int>,int>mp;
int f[N],rk[N],ans[N],last,n,m;
struct revo
{int fax,fay;int rkx,rky;
};
struct Node
{int l,r;vector<pair<int,int>>node;//位于[l,r]这段时间内的边有哪些
}tree[N<<2];
int find(int x){return f[x]==x?x:find(f[x]);}
revo merge(int x,int y)//并查集的合并,返回合并之前的信息revo用于撤销
{revo ans;int xx=find(x),yy=find(y);ans.fax=xx,ans.fay=yy;ans.rkx=rk[xx],ans.rky=rk[yy];if(xx!=yy){if(rk[xx]>rk[yy]) swap(xx,yy);f[xx]=yy;rk[yy]=max(rk[yy],rk[xx]+1);}return ans;
}
void revocation(stack<revo>&st)//并查集的撤销,将并查集恢复至node状态
{while(st.size()){revo a=st.top();f[a.fax]=a.fax,f[a.fay]=a.fay;rk[a.fax]=a.rkx,rk[a.fay]=a.rky;st.pop();}
}
void build(int k,int l,int r)
{tree[k].l=l,tree[k].r=r;if(l==r) return;int mid=(l+r)>>1;build(k<<1,l,mid),build(k<<1|1,mid+1,r);
}
void update(int k,int l,int r,pair<int,int>val)
{if(l>r) return;if(tree[k].l>r||tree[k].r<l) return;if(tree[k].l>=l&&tree[k].r<=r){tree[k].node.push_back(val);return;}update(k<<1,l,r,val),update(k<<1|1,l,r,val);
}
void dfs(int k)//线段树分治
{stack<revo>st;for(auto it:tree[k].node) if(mp[it]) st.push(merge(it.first,it.second));//并查集的合并if(tree[k].l==tree[k].r){int id=tree[k].l;if(q[id].op==2) last=ans[id]=(find(q[id].x)==find(q[id].y));q[id+1].x=(q[id+1].x+last-1)%n+1,q[id+1].y=(q[id+1].y+last-1)%n+1;if(q[id+1].x>q[id+1].y) swap(q[id+1].x,q[id+1].y);if(q[id+1].op==1) mp[{q[id+1].x,q[id+1].y}]^=1;revocation(st);return;}else dfs(k<<1),dfs(k<<1|1);revocation(st);
}
void init(){for(int i=1;i<N;i++) f[i]=i,rk[i]=1;}
int main()
{#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);init();read(n),read(m);build(1,1,m);for(int i=1,x,y,op;i<=m;i++){read(op),read(x),read(y);q[i]={op,x,y};if(op==2) continue;if(x>y) swap(x,y);if(mp[{x,y}]) update(1,mp[{x,y}],i,{x,y});mp[{x,y}]=i;x=x%n+1,y=y%n+1;if(x>y) swap(x,y);if(mp[{x,y}]) update(1,mp[{x,y}],i,{x,y});mp[{x,y}]=i;}for(auto it:mp) update(1,it.second,m,it.first);mp.clear();if(q[1].op==1) mp[{min(q[1].x,q[1].y),max(q[1].x,q[1].y)}]=1;memset(ans,-1,sizeof(ans));dfs(1);for(int i=1;i<=m;i++) if(ans[i]!=-1) write(ans[i]);return 0;
}

CodeForces - 1217F Forced Online Queries Problem(线段树分治+并查集撤销)相关推荐

  1. 牛客多校8 - All-Star Game(线段树分治+并查集按秩合并的撤销操作)

    题目链接:点击查看 题目大意:有 n 个球员和 m 个球迷,一个球员可能是多个球迷的粉丝,需要选择最少的球员进行比赛,使得所有的球迷都愿意观看(对于每个球迷来说,都有至少一个其喜欢的球员入选比赛) 对 ...

  2. 越野赛车问题——线段树分治+并查集

    题目 [题目描述] 小 $H$ 是一位优秀的越野赛车女选手.现在她准备在 $A$ 山上进行赛车训练. $A$ 山上一共有 $n$ 个广场,编号依次为 $1$ 到 $n$ ,这些广场之间通过 $n-1$ ...

  3. BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)

    传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...

  4. Codeforces 1140F 线段树 分治 并查集

    题意及思路:https://blog.csdn.net/u013534123/article/details/89010251 之前cf有一个和这个相似的题,不过那个题只有合并操作,没有删除操作,直接 ...

  5. bzoj4025-二分图【线段树分治,并查集】

    正题 题目链接:https://darkbzoj.tk/problem/4025 题目大意 nnn个点mmm条边,每条边会在一个TTT以内的时间段内出现,对于任意一个TTT以内的时刻求图是否是一个二分 ...

  6. BZOJ4399魔法少女LJJ——线段树合并+并查集

    题目描述 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了 LJJ感叹道"这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着醉 ...

  7. Codeforces.1051G.Distinctification(线段树合并 并查集)

    题目链接 \(Description\) 给定\(n\)个数对\(A_i,B_i\).你可以进行任意次以下两种操作: 选择一个位置\(i\),令\(A_i=A_i+1\),花费\(B_i\).必须存在 ...

  8. c++自带的可持久化平衡树?rope大法好!(超详细解答 + 5道例题讲解,可直接替代可持久化的线段树、并查集、平衡树!)

    整理的算法模板合集: ACM模板 目录 c++自带的可持久化平衡树?rope大法好! 1. 声明 2. 支持操作 char类型的rope int类型的rope 3. 具体的细节 4. "可持 ...

  9. [NOI2018] 归程(线段树维护并查集的可持久化/kruskal重构树,倍增+dijkstra最短路)

    [NOI2018] 归程 description solution1 code1 solution2 code description 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要 ...

最新文章

  1. 边缘计算架构_边缘计算架构梳理
  2. 图文并茂重新认识下递归
  3. google i/o_Google I / O 2017最有希望的突破
  4. ajax提交输入内容,当输入用于提交时,AJAX表单提交
  5. 郑大中科院合作计算机系,郑大一本今年在河南招4320人 本科新增5个专业
  6. mysql hy000 2013_MySQLERROR2013(HY000)错误解决方法
  7. C++ 时间操作(获取毫秒级)【转】
  8. 使用.NET和Jquery打造简单的便签纸
  9. 华为服务器怎么装win7系统教程视频教程,华为交换机配置教程|华为交换机配置视频教程完整版...
  10. 威纶和s7200通讯线_威纶触摸屏如何与西门子PLC进行通信,教你两种方法吧!
  11. C++ WinHTTP实现文件下载
  12. 百度地图、腾讯地图、高德地图经纬度转换
  13. R学习之统计算法与R优化包(矩估计法也即Newton) --(R语言编程)-----数模
  14. 問題の解決策 [USACO18JAN]Lifeguards P(题解)
  15. PS-Photoshop2020版安装包以及安装详细教程
  16. 前端词汇(后续整理)
  17. freetype用法
  18. 《棒球裁判》:走近棒球运动·球赛规则
  19. 【清华集训2014】玛里苟斯
  20. 2023湖北师范大学计算机考研信息汇总

热门文章

  1. 解决方案 | tensorflow安装慢解决方案
  2. mysql启动集群报连接本地失败_启动本地安装的pxc集群失败,前面的步骤都检查没错了...
  3. 根目录android结构,android系统盘根目录中的(文件)谁给讲一下是干什么的?
  4. Nacos源码InstanceController
  5. 分布式事务中的2PC
  6. Executor家族的辨析
  7. kafka高可用集群课程介绍
  8. 使用Stream流的方式,遍历集合,对集合中的数据进行过滤
  9. 使用固态存储SSD或PCIe卡
  10. 华为云服务器芯片,云服务器芯片