题意

题目链接

动态图连通性,加密方式为 \((x+l-1)\bmod n +1\) (\(l=[上一次询问的两点连通]\))。

点数 \(n\),操作数 \(m\) \(\le 2\times 10^5\)。

Solution

容易发现这是一个假的强制在线—— \(l\) 的取值只有 \(0\) 和 \(1\) 两种,所以总共的操作种数不超过 \(2\times m\)。

于是我们可以考虑采用离线解决本题的思路,我们考虑线段树分治+可撤销并查集。

与离线不同的是,我们需要动态在线段树上添加节点。

具体而言,我们维护每条边的时间区间,每遍历到一个叶子结点上的修改,就维护对应边的时间区间,同时在线段树上进行插入。

code

#include<bits/stdc++.h>
using namespace std;
namespace io {
const int SIZE=(1<<21)+1;
char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];
#define gc()(iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
inline int gi (){ int x;
for(c=gc();c<'0'||c>'9';c=gc());
for(x=0;c<='9'&&c>='0';c=gc()) x=(x<<1)+(x<<3)+(c&15); return x;
}
} using io::gi;
const int N=2e5+5;
typedef pair<int,int> pr;
struct query
{
int op,x0,y0,x1,y1;
bool vis[2];
pr nxt0,nxt1;
} q[N];
vector<pr> st[N<<2];
int n,m,f[N],rk[N],stk[N],tp,lst;
map<pr,int> mp; int mid; pr pre[N<<1];
#define lx (x<<1)
#define rx (x<<1|1)
int findset(int u)
{
return f[u]?findset(f[u]):u;
}
void unionset(int u, int v)
{
u=findset(u),v=findset(v);
if(u!=v)
{
if (rk[u]<rk[v]) swap(u,v);
f[v]=u,rk[u]+=rk[v];
stk[++tp]=v;
}
}
void update(int x, int l, int r, int sl, int sr, pr w)
{
if(sl>sr) return ;
if(sl<=l&&r<=sr)
{
st[x].push_back(w);
return ;
}
int mid=l+r>>1;
if(sl<=mid) update(lx,l,mid,sl,sr,w);
if(sr>mid) update(rx,mid+1,r,sl,sr,w);
}
void solve(int x, int l, int r)
{
int now=tp;
for(auto i:st[x]) unionset(i.first,i.second);
if(l==r)
{
int nu=q[l].x0,nv=q[l].y0,lu=q[l].x1,lv=q[l].y1,nvis=q[l].vis[0],lvis=q[l].vis[1],r=0;
pr nnxt=q[l].nxt0,lnxt=q[l].nxt1;
if(lst) swap(nu,lu),swap(nv,lv),swap(nvis,lvis),swap(nnxt,lnxt),r=1;
if(q[l].op==2)
printf("%d",lst=(findset(nu)==findset(nv)));
else
{
if(!nvis)
{
update(1,1,m,l+1,nnxt.first-1,make_pair(nu,nv));
q[nnxt.first].vis[nnxt.second]=true;
}
if(lvis)
{
update(1,1,m,l+1,lnxt.first-1,make_pair(lu,lv));
q[lnxt.first].vis[lnxt.second]=true;
}
}
}
else
{
int mid=l+r>>1;
solve(lx,l,mid),solve(rx,mid+1,r);
}
for(;tp>now;--tp) rk[f[stk[tp]]]-=rk[stk[tp]],f[stk[tp]]=0;
}
int main()
{
n=gi(),m=gi();
for(int i=1;i<=n;++i) rk[i]=1;
for(int i=1;i<=m;++i)
{
q[i].op=gi(),q[i].x0=gi(),q[i].y0=gi();
if(q[i].x0>q[i].y0) swap(q[i].x0,q[i].y0);
q[i].x1=q[i].x0%n+1,q[i].y1=q[i].y0%n+1;
if(q[i].x1>q[i].y1) swap(q[i].x1,q[i].y1);
}
for(int i=m;i;--i)
{
if(q[i].op==2) continue;
int tid=mp[make_pair(q[i].x0,q[i].y0)];
if(!tid) q[i].nxt0=make_pair(m+1,0),tid=mp[make_pair(q[i].x0,q[i].y0)]=++mid;
else q[i].nxt0=pre[tid];
if(q[i].op==1) pre[tid]=make_pair(i,0);
tid=mp[make_pair(q[i].x1,q[i].y1)];
if(!tid) q[i].nxt1=make_pair(m+1,0),tid=mp[make_pair(q[i].x1,q[i].y1)]=++mid;
else q[i].nxt1=pre[tid];
pre[tid]=make_pair(i,1);
}
solve(1,1,m);
}

【CF1217F】Forced Online Queries Problem的更多相关文章

  1. 【BZOJ3489】A simple rmq problem(KD-Tree)

    [BZOJ3489]A simple rmq problem(KD-Tree) 题面 BZOJ 题解 直接做肯定不好做,首先我们知道我们是一个二维平面数点,但是限制区间只能出现一次很不好办,那么我们给 ...

  2. 【CF903G】Yet Another Maxflow Problem 线段树

    [CF903G]Yet Another Maxflow Problem 题意:一张图分为两部分,左边有n个点A,右边有m个点B,所有Ai->Ai+1有边,所有Bi->Bi+1有边,某些Ai ...

  3. 【CF710F】String Set Queries(二进制分组,AC自动机)

    [CF710F]String Set Queries(二进制分组,AC自动机) 题面 洛谷 CF 翻译: 你有一个字符集合\(D\),初始为空, 有三种操作: 往\(D\)中加入一个串:从\(D\)中 ...

  4. 【CF938G】Shortest Path Queries(线段树分治,并查集,线性基)

    [CF938G]Shortest Path Queries(线段树分治,并查集,线性基) 题面 CF 洛谷 题解 吼题啊. 对于每个边,我们用一个\(map\)维护它出现的时间, 发现询问单点,边的出 ...

  5. 【BZOJ3489】A simple rmq problem

    [BZOJ3489]A simple rmq problem 题面 bzoj 题解 这个题不强制在线的话随便做啊... 考虑强制在线时怎么搞 预处理出一个位置上一个出现的相同数的位置\(pre\)与下 ...

  6. 【BZOJ3489】A simple rmq problem kd-tree

    [BZOJ3489]A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过 ...

  7. 【题解】CF986E Prince's Problem(树上差分+数论性质)

    [题解]CF986E Prince's Problem(树上差分+数论性质) 题目大意: 给定你一棵树,有点权\(val_i\le 10^7\).现在有\(m\)组询问给定参数\(x,y,w\)问你对 ...

  8. 【动态规划】Codeforces 706C Hard problem

    题目链接: http://codeforces.com/contest/706/problem/C 题目大意: n(2 ≤ n ≤ 100 000)个字符串(长度不超过100000),翻转费用为Ci( ...

  9. 【BZOJ】1700: [Usaco2007 Jan]Problem Solving 解题

    [题意]给定n道题,每月末发放工资m,要求从1解到n,每道题需要在当月初付费ai,下月初付费bi,多道题可以安排在同月,求最少月数. [算法]DP [题解]参考自:[bzoj1700]Problem ...

随机推荐

  1. EAP认证

    EAP信息交换: 上图中展示的是OTP(一次性密码)实现EAP交换过程,具体的EAP交换过程如下: 步骤1:请求方向认证方发送EAPOL-Start消息,通知对方已经做到了认证准备(注意:若会话由认证 ...

  2. 编译安装nginx错误解决!

    编译安装执行 ./configure --prefix=/root/web/nginx --sbin-path=/root/web/nginx/sbin/nginx --conf-path=/root ...

  3. python浅析格式化输出和深浅copy

    一,格式化输出 今天主要想记录一下关于格式化输出的例子,然后结合了自己的理解,分析如下: 格式是 :百分号+占位符 主要有三种使用形式:%s  (其中s表示string)表示字符串 %d  (其中d表 ...

  4. Android Studio中 安卓模拟器 联网

    方案一:之前做测试的时候发现虚拟机无法联网(浏览器打开 www.baidu.com, 显示 403 forbidden): 解决方案:关闭已经打开的虚拟机,进入到 SDK 安装目录下,按住 shift ...

  5. Unity - 求反射向量 (2d)

    求反射向量 https://www.cnblogs.com/graphics/archive/2013/02/21/2920627.html 上面是大佬的公式可以去看一下 借的大佬的图 1.求入射向量 ...

  6. Airless Pump Bottle For The Rise Of Cosmetic Packaging Solutions

    Airless Pump Bottle    are used in the rise of cosmetic packaging solutions. According to the suppli ...

  7. Java基础知识笔记第一章:入门

    java的地位: java具有面向对象,与平台无关,安全,稳定和多线程等优良特性,是目前软件设计中优秀的编程语言. java的特点: 1.简单 2.面向对象 3.平台无关 jre(java runti ...

  8. day4-2数组及方法

    数组: Js数组 可以存放任意数据类型的数据 如果索引大于数组的长度,数组自动增加到该索引值加1的长度 var arr = ["terry","larry",& ...

  9. C语言程序编译

    原来GCC的含义是GNU C Compiler,当初知识编译C语言,而现在GCC不知编译C语言,除此之外它还支持编译Ada.C++.Java.Object C.Pascal.COBOL.等等许多语言, ...

  10. android开发如何在页面之间传参

    第一个页面跳转 传递值 Button bn1=(Button)findViewById(R.id.btn_Login); //跳转bn1.setOnClickListener(new OnClickL ...