【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\n",-1);
      else
      { 
        split(n+1,y);
        printf("%d\n",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; 
}

 

posted @ 2018-06-18 00:40  尹吴潇  阅读(223)  评论(0编辑  收藏  举报