• 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;
    }
  • 相关阅读:
    scala学习笔记:理解stream和view
    scala学习笔记:变量声明中的模式
    scala学习笔记:理解并行集合par
    快速了解Scala技术栈
    scala学习笔记:控制抽象
    scala中的call-by-name和call-by-value
    scala学习笔记:各种奇怪的写法
    scala学习笔记:match与unapply()
    scala学习笔记:无参函数
    scala学习笔记:函数与方法
  • 原文地址:https://www.cnblogs.com/Narh/p/10372849.html
Copyright © 2020-2023  润新知