线段树分治[模板]

线段树分治,是一种离线后在时间轴上用线段树维护区间操作,并可以进行撤销的思想。

二分图 /【模板】线段树分治

\(\text{Solution}:\)

二分图的充要条件是不存在奇环,可以用扩展域并查集维护。把 \([l,r]\) 区间内的边分为 \(\log\) 段挂在线段树的对应节点上,遍历到这个节点时把所有边合并并完成查询。由于并查集需要可撤销,故需要按秩合并或者启发式合并。

\(\text{Code}:\)

#include <bits/stdc++.h>
//#pragma GCC optimize(3)
#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
using namespace std; const int N=200010;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,m,K,U[N],V[N],f[N],d[N];
vector<int> e[N<<2];
pair<int,int> sta[N<<3]; int tp;
#define lc (x<<1)
#define rc (x<<1|1)
void Insert(int u,int v,int l,int r,int x,int id)
{
	if(l>=u&&r<=v)
	{
		e[x].eb(id);
		return;
	}
	int mid=(l+r)/2;
	if(u<=mid) Insert(u,v,l,mid,lc,id);
	if(v>mid) Insert(u,v,mid+1,r,rc,id);
}
inline int Find(int x)
{
	while(x^f[x]) x=f[x];
	return x;
}
inline void Merge(int x,int y)
{
	int fx=Find(x), fy=Find(y);
	if(fx==fy) return;
	if(d[fx]>d[fy]) swap(fx,fy);
	sta[++tp]=mk(fx,d[fx]==d[fy]);
	f[fx]=fy, d[fy]+=d[fx]==d[fy];
}
void Get(int x,int l,int r)
{
	int flg=1;
	int pre=tp;
	for(ri int i=0;i<(int)e[x].size();i++)
	{
		int fx=Find(U[e[x][i]]), fy=Find(V[e[x][i]]);
		if(fx==fy)
		{
			for(ri int j=l;j<=r;j++) puts("No");
			flg=0;
			break;
		}
		Merge(U[e[x][i]]+n,fy), Merge(V[e[x][i]]+n,fx);
	}
	if(flg)
	{
		if(l==r) puts("Yes");
		else
		{
			int mid=(l+r)/2;
			Get(lc,l,mid), Get(rc,mid+1,r);
		}
	}
	while(tp>pre)
	{
		pair<int,int> p=sta[tp];
		d[f[p.fi]]-=p.se, f[p.fi]=p.fi;
		sta[tp--]=mk(0,0);
	}
}
signed main()
{
	n=read(), m=read(), K=read();
	for(ri int i=1;i<=m;i++)
	{
		U[i]=read(), V[i]=read();
		int l,r;
		l=read(), r=read();
		Insert(l+1,r,1,K,1,i);
	}
	for(ri int i=1;i<=n+n;i++) f[i]=i;
	Get(1,1,K);
	return 0;
}

「离线可过」动态图连通性

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
using namespace std; const int N=5010, M=500010;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,m,T,f[N],siz[N],Ans[M];
vector<int> e[M<<2];
unordered_map<int,int> In[N];
struct Temp
{
	int u,v,l,r;
}tmp[M]; int cnt;
int U[M],V[M];
int sta[M<<2],tp;
#define lc (x<<1)
#define rc (x<<1|1)
void Insert(int u,int v,int l,int r,int x,int id)
{
	if(l>=u&&r<=v)
	{
		e[x].eb(id);
		return;
	}
	int mid=(l+r)/2;
	if(u<=mid) Insert(u,v,l,mid,lc,id);
	if(v>mid) Insert(u,v,mid+1,r,rc,id);
}
inline int Find(int x)
{
	while(x^f[x]) x=f[x];
	return x;
}
inline void Merge(int x,int y)
{
	int fx=Find(x), fy=Find(y);
	if(fx==fy) return;
	if(siz[fx]>siz[fy]) swap(fx,fy);
	f[fx]=fy, siz[fy]+=siz[fx];
	sta[++tp]=fx;
}
void Get(int x,int l,int r)
{
	int pre=tp;
	for(ri int i=0;i<(int)e[x].size();i++) Merge(tmp[e[x][i]].u,tmp[e[x][i]].v);
	if(l==r)
	{
		if(Find(U[l])==Find(V[l])) puts("Y");
		else puts("N");
	}
	else
	{
		int mid=(l+r)/2;
		Get(lc,l,mid), Get(rc,mid+1,r);
	}
	while(tp>pre)
	{
		int p=sta[tp];
		siz[f[p]]-=siz[p];
		f[p]=p;
		sta[tp--]=0;
	}
}
#undef lc
#undef rc
signed main()
{
	n=read(), m=read();
	for(ri int i=1;i<=m;i++)
	{
		int opt,x,y;
		opt=read(), x=read(), y=read();
		if(x>y) swap(x,y);
		if(!opt) In[x][y]=T+1;
		else if(opt==1)
		{
			if(In[x][y]<=T) tmp[++cnt]=(Temp){x,y,In[x][y],T};
			In[x].erase(In[x].find(y));
		}
		else U[++T]=x, V[T]=y;
	}
	if(!T) return 0;
	for(ri int i=1;i<=cnt;i++) Insert(tmp[i].l,tmp[i].r,1,T,1,i);
	for(ri int i=1;i<=n;i++)
	{
		for(auto j:In[i])
		{
			tmp[++cnt]=(Temp){i,j.fi,j.se,T};
			Insert(tmp[cnt].l,tmp[cnt].r,1,T,1,cnt);
		}
	}
	for(ri int i=1;i<=n;i++) f[i]=i, siz[i]=1;
	Get(1,1,T);
	return 0;
}
posted @ 2021-02-22 15:36  zkdxl  阅读(102)  评论(0编辑  收藏  举报