【CF1217F】Forced Online Queries Problem

题意

题目链接

动态图连通性,加密方式为 \((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);
}
posted @ 2019-09-28 10:35  x_faraway_x  阅读(291)  评论(0编辑  收藏  举报