zoukankan      html  css  js  c++  java
  • 【BZOJ4764】弹飞大爷

    题解:

    这个应该还是比较简单的

    首先比较容易想到用lct来维护

    我们可以建立一个特殊点

    然后我们要处理环

    其实只要判断它和不和这个特殊点联通就行了

    那么当它不是环了我们怎么还原呢

    只要对每个在根节点记录一下lazy标记 然后处理一下就好了

    代码:

     

    #include <bits/stdc++.h>
    using namespace std;
    #define lowbit(x) (x&(-x))
    #define ll long long
    #define IL inline
    #define rint register int 
    #define me(x) memset(x,0,sizeof(x))
    #define fi first
    #define se second
    #define mid ((h+t)>>1)
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    #define setit set<int>::iterator
    const int INF=1e9;
    char ss[1<<24],*A=ss,*B=ss;
    IL char gc()
    {
      return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    }
    template<class T> read(T &x)
    {
      rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=c^48;
      while (c=gc(),47<c&&c<58) x=(x<<3)+(x<<1)+(c^48);
      x*=f;
    }
    const int N=6e5;
    int fa[N],ls[N],rs[N],count2[N],p[N];
    bool rev[N];
    struct re{
      int a,b;
    }lazy[N];
    IL void updata(int x)
    {
      count2[x]=count2[ls[x]]+count2[rs[x]]+1;
    }
    IL bool pd(int x)
    {
      int fa1=fa[x];
      if (ls[fa1]!=x&&rs[fa1]!=x) return(0);
      else return(1);
    }
    IL void down(int x)
    {
      if (!rev[x]) return;
      swap(ls[x],rs[x]);
      rev[ls[x]]^=1; rev[rs[x]]^=1;
      rev[x]=0;
    }
    void rotate(int x,int y)
    {
      int fa1=fa[x];
      if (y==1)
      {
        rs[fa1]=ls[x];
        if (ls[x]) fa[ls[x]]=fa1;
      } else
      {
        ls[fa1]=rs[x];
        if (rs[x]) fa[rs[x]]=fa1;
      }
      fa[x]=fa[fa1];
      if (pd(fa1))
      {
        if (ls[fa[fa1]]==fa1) ls[fa[fa1]]=x; else rs[fa[fa1]]=x;
      }
      fa[fa1]=x;
      if (y==1) ls[x]=fa1; else rs[x]=fa1;
      updata(fa1); updata(x);
    }
    void dfs(int x)
    {
      if (pd(x)) dfs(fa[x]);
      down(x);
    }
    void splay(int x)
    {
      dfs(x);
      int fa1=fa[x];
      while (pd(x))
      {
        if (!pd(fa1))
        {
          if (x==ls[fa1]) rotate(x,2); else rotate(x,1);
        } else
        if (ls[fa[fa1]]==fa1)
          if (ls[fa1]==x)
            rotate(fa1,2),rotate(x,2);
          else 
            rotate(x,1),rotate(x,2);
        else
          if (rs[fa1]==x)
            rotate(fa1,1),rotate(x,1);
          else 
            rotate(x,2),rotate(x,1);
        fa1=fa[x];
      }
    }
    void access(int x)
    {
      for (int y=0;x;y=x,x=fa[x])
      {
        splay(x);
        rs[x]=y,updata(x);
      }
    }
    void mkr(int x)
    {
      access(x);
      splay(x);
      rev[x]^=1;
    }
    int fdr(int x)
    {
      access(x);
      splay(x);
      while(ls[x]) x=ls[x];
      return(x);
    }
    void split(int x,int y)
    {
      mkr(x);
      access(y);
      splay(y); 
    }
    void link(int x,int y)
    {
      mkr(x);
      if (fdr(y)!=x) fa[x]=y;
      else
      {
        int x1=fdr(y);
        lazy[x1].a=x,lazy[x1].b=y;
      }
    }
    void cut(int x,int y)
    {
      int x1=fdr(x);
      if ((lazy[x1].a==x&&lazy[x1].b==y)||(lazy[x1].a==y&&lazy[x1].b==x))
      {
        lazy[x1].a=lazy[x1].b=0;
      } else
      {
        int tmp1=lazy[x1].a,tmp2=lazy[x1].b;
        lazy[x1].a=lazy[x1].b=0;
        mkr(x);
        access(y);
        splay(y);
        fa[x]=ls[y]=0;
        updata(y);
        if (tmp1!=0)
        {
          link(tmp1,tmp2);
        }
      } 
    }
    int n,m;
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      read(n); read(m);
      int k;
      rep(i,1,n) count2[i]=1;
      rep(i,1,n)
      {
        read(k);
        p[i]=k;
        if (i+k<=n&&i+k>=1)
        {
          link(i,i+k);
        } else link(i,n+1);
      }
      rep(i,1,m)
      {
        int x,y,z;
        read(x); read(y);
        if (x==1)
        {
          access(y);
          int x1=fdr(y);
          if (lazy[x1].a) printf("%d
    ",-1);
          else
          { 
            split(n+1,y);
            printf("%d
    ",count2[y]-1);
          }
        } else
        {
          read(z);
          if (y+p[y]<=n&&y+p[y]>=1) cut(y,y+p[y]);
          else cut(y,n+1);
          if (y+z<=n&&y+z>=1) link(y,y+z);
          else link(y,n+1);
          p[y]=z;
        }
      }
      return 0; 
    }
  • 相关阅读:
    组合模式
    HashMap,ArrayList扩容
    Maven入门使用(一)
    OutputStreamWriter API 以及源码解读
    java.io.BufferedWriter API 以及源码解读
    java.io.writer API 以及 源码解读
    自定义redis序列化工具
    策略模式
    Spring下redis的配置
    简单工厂模式
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9194232.html
Copyright © 2011-2022 走看看