bzoj 4025 二分图——线段树分治+LCT

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4025

线段树分治,用 LCT 维护链的长度即可。不过很慢。

正常(更快)的方法应该是线段树分治+并查集(按秩合并,链长可以暴力爬)或者 LCT 维护删除时间最大生成树。就不写了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ls Ls[cr]
#define rs Rs[cr]
#define lc c[x][0]
#define rc c[x][1]
#define pb push_back
using namespace std;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
const int N=1e5+5,M=2e5+5;
int n,m,fa[N],c[N][2],rev[N],siz[N],stk[N],tp;
int tot,Ls[M],Rs[M],top;
struct Node{
  int x,y;
  Node(int x=0,int y=0):x(x),y(y) {}
}sta[N];
vector<Node> vt[M];

void build(int l,int r,int cr)
{
  if(l==r)return; int mid=l+r>>1;
  ls=++tot; build(l,mid,ls);
  rs=++tot; build(mid+1,r,rs);
}
void ins(int l,int r,int cr,int L,int R,Node k)
{
  if(l>=L&&r<=R){vt[cr].pb(k);return;}
  int mid=l+r>>1;
  if(L<=mid)ins(l,mid,ls,L,R,k);
  if(mid<R)ins(mid+1,r,rs,L,R,k);
}

bool isrt(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
void pshp(int x){siz[x]=siz[lc]+siz[rc]+1;}
void Rev(int x){if(rev[x]){rev[x]=0;rev[lc]^=1;rev[rc]^=1;swap(lc,rc);}}
void rotate(int x)
{
  int y=fa[x],z=fa[y],d=(x==c[y][1]);
  if(!isrt(y))c[z][y==c[z][1]]=x;
  fa[x]=z;
  fa[y]=x; fa[c[x][!d]]=y;
  c[y][d]=c[x][!d]; c[x][!d]=y;
  pshp(y); pshp(x);
}
void splay(int x)
{
  stk[tp=1]=x;
  for(int k=x;!isrt(k);k=fa[k])stk[++tp]=fa[k];
  for(int i=tp;i;i--)Rev(stk[i]);
  int y,z;
  while(!isrt(x))
    {
      y=fa[x]; z=fa[y];
      if(!isrt(y))
    ( (x==c[y][0])^(y==c[z][0]) )?rotate(x):rotate(y);
      rotate(x);
    }
}
void access(int x)
{
  for(int t=0;x;splay(x),rc=t,pshp(x),t=x,x=fa[x]);
}
void mkrt(int x)
{
  access(x); splay(x); rev[x]^=1;
}
void split(int x,int y)
{
  mkrt(x); access(y); splay(y);
}
bool link(Node k)
{
  int x=k.x, y=k.y; split(x,y);
  int cr=y; while(c[cr][0])cr=c[cr][0];
  if(cr==x) return (siz[y]&1);
  sta[++top]=k; fa[x]=y; return false;
}
void cut(Node k)
{
  int x=k.x, y=k.y; split(x,y);
  c[y][0]=fa[x]=0; pshp(y);
}
void solve(int l,int r,int cr)
{
  int sz=vt[cr].size(); bool flag=0;
  for(int i=0;i<sz;i++)
    {
      flag=link(vt[cr][i]); if(flag)break;
    }
  if(flag){for(int i=l;i<=r;i++)puts("No");return;}
  if(l==r){puts("Yes");return;}
  int mid=l+r>>1,nw=top;
  solve(l,mid,ls); for(int& i=top;i>nw;i--)cut(sta[i]);
  solve(mid+1,r,rs); for(int& i=top;i>nw;i--)cut(sta[i]);
}
int main()
{
  n=rdn();int T=rdn();m=rdn();
  tot=1;build(1,m,1);
  for(int i=1;i<=n;i++)siz[i]=1;
  for(int i=1,u,v,st,en;i<=T;i++)
    {
      u=rdn();v=rdn();st=rdn()+1;en=rdn();
      ins(1,m,1,st,en,Node(u,v));
    }
  solve(1,m,1); return 0;
}

猜你喜欢

转载自www.cnblogs.com/Narh/p/10372849.html