Very Long Suffix Array

题解:

原来动态开点平衡树是O(n)空间的。。

只需要在split的查找和出来之后动态开点就可以了

这题的结论是2^(b[a[i]+1]>b[a[i+1]+1]的个数)

前60分是普通的平衡树操作完之后再算

满分是动态开点平衡树

对于一个点内部的统计一下,边界上的特判一下

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
#define ll long long
#define mid ((h+t)>>1)
#define mep(x,y) memcpy(x,y,sizeof(y))
namespace IO
{
    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>void read(T &x)
    {
        rint f=1,c;while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
        while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
    }
    char sr[1<<24],z[20]; int C=-1,Z;
    template<class T>void wer(T x)
    {
        if (x<0) sr[++C]='-',x=-x; 
        while (z[++Z]=x%10+48,x/=10);
        while (sr[++C]=z[Z],--Z);
    }
    IL void wer1() {sr[++C]=' ';}
    IL void wer2() {sr[++C]='\n';}
    template<class T>IL void maxa(T &x,T y) { if (x<y) x=y;}
    template<class T>IL void mina(T &x,T y) { if (x>y) x=y;}
    template<class T>IL T MAX(T x,T y){ return x>y?x:y;}
    template<class T>IL T MIN(T x,T y){ return x<y?x:y;}
}
using namespace IO;
const int N=9e5;
int a[N],b[N],xl[N],cnt,dy[N],d[N],tmp;
const int mo=1e9+7;
struct re{
    int a,b,kk,d;
}c[N],f[N],p[N],c1[N];
int nq;
struct phs{
    int fa[N],rs[N],ls[N],num[N],o[N],v[N],cnt,cnt3;
    bool rev[N],t[N];
    IL void updata(int x)
    {
        num[x]=num[ls[x]]+num[rs[x]]+o[x];
    }
    IL void down(int x)
    {
        if (rev[x])
        {
            swap(ls[ls[x]],rs[ls[x]]);
            swap(ls[rs[x]],rs[rs[x]]);
            rev[ls[x]]^=1; rev[rs[x]]^=1;
            t[ls[x]]^=1; t[rs[x]]^=1;
            rev[x]=0;
        } 
    }
    void rotate(int x,int y)
    {
        int f1=fa[x];
        if (y==1)
        {
            rs[f1]=ls[x];
            if (ls[x]) fa[ls[x]]=f1;
        } else
        {
            ls[f1]=rs[x];
            if (rs[x]) fa[rs[x]]=f1;
        }
        fa[x]=fa[f1];
        if (fa[f1])
        {
            if (ls[fa[f1]]==f1) ls[fa[f1]]=x; else rs[fa[f1]]=x;
        }
        fa[f1]=x;
        if (y==1) ls[x]=f1; else rs[x]=f1;
        updata(f1); updata(x);
    }
    void dfs(int x)
    {
        if (fa[x]) dfs(fa[x]);
        down(x);
    }
    IL void splay(int x,int y)
    {
        dfs(x);
        int f1=fa[x];
        while (f1!=y)
        {
            if (fa[f1]==y)
              if (ls[f1]==x) rotate(x,2); else rotate(x,1);
            else 
              if (ls[fa[f1]]==f1) 
                if (ls[f1]==x) rotate(f1,2),rotate(x,2);
                else rotate(x,1),rotate(x,2);
              else if (rs[f1]==x) rotate(f1,1),rotate(x,1);
                else rotate(x,2),rotate(x,1);
            f1=fa[x];
        }
    }
    IL int sc(int x,int y)
    {
        if (t[x])
        {
          o[++nq]=y; num[nq]=y; fa[nq]=x; v[nq]=v[x];
          ls[nq]=ls[x]; o[x]-=y;
          v[x]+=y; ls[x]=nq; t[nq]=t[x];
        } else
        {
            o[++nq]=y; num[nq]=y; fa[nq]=x; v[nq]=v[x]+o[x]-y;
          ls[nq]=ls[x]; o[x]-=y;
          ls[x]=nq; t[nq]=t[x];
        }
        if (ls[nq]) fa[ls[nq]]=nq;
        num[nq]+=num[ls[nq]];
        return nq;
    }
    IL int search(int y)
    {
        splay(1,0);
        int x=1;
        while (1)
        {
            down(x);
            if (num[ls[x]]+o[x]>=y&&num[ls[x]]<y)
            {
               if (num[ls[x]]+o[x]==y) return(x);
               return sc(x,y-num[ls[x]]);
            }
            if (num[ls[x]]+o[x]>y) x=ls[x];
            else y-=num[ls[x]]+o[x],x=rs[x];
        }
    }
    IL int split(int x,int y)
    {
        int k1=search(x),k2=search(y+2);
        splay(k1,0); 
        splay(k2,k1);
        if (o[k2]!=1)
          sc(k2,o[k2]-1);
        return ls[k2];
    }
    IL void reverse(int x,int y)
    {
        int k=split(x,y);
        rev[k]^=1; swap(ls[k],rs[k]); t[k]^=1;
    }
    IL void change(int x,int y)
    {
        int k=split(x,y);;
        int now=fa[k];
        ls[now]=0; fa[k]=0; splay(now,0); 
        now=search(2);
        splay(now,0); down(now); down(1);
        rs[1]=k; fa[k]=1; splay(k,0);
    }
    void dfs2(int x)
    {
        down(x);
        if (ls[x]) dfs2(ls[x]);
    //    a[++cnt]=v[x];
        c[++cnt]=(re){v[x],o[x],t[x],cnt3+1};
        cnt3+=o[x];
        if (rs[x]) dfs2(rs[x]);
    }
}S;
bool cmp(re x,re y)
{
    return x.a<y.a;
}
IL int pos(int x)
{
    if (x>tmp) return(0);
    int h=1,t=S.cnt-2;
    while (h<t)
    {
        if (f[mid].a+f[mid].b-1>=x) t=mid;
        else h=mid+1;
    }
    if (f[h].kk) return f[h].d+x-f[h].a;
    else return f[h].d+f[h].b-1-(x-f[h].a);
}
IL int pos2(int x)
{
    if (c[x].kk) return c[x].a;
    else return c[x].a+c[x].b-1;
}
IL int fsp(ll x,int y)
{
    ll ans=1;
    while (y)
    {
        if (y&1) ans=ans*x%mo;
        x=x*x%mo; y>>=1;
    }
    return ans;
}
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    int n,m;
    read(n); read(m);
    tmp=n;
    int cnt=0;
    nq=3;
    S.rs[1]=2; S.rs[2]=3; S.fa[2]=1; S.fa[3]=2; S.t[2]=1;
    S.o[1]=1; S.v[1]=0; S.o[2]=n; S.v[2]=1; S.o[3]=1; S.v[3]=n+1;
    S.splay(3,0);
    rep(i,1,m)
    {
        int kk,x,y;
        read(kk); read(x); read(y);
        if (kk==0) S.change(x,y);
        else S.reverse(x,y);
    }
    S.splay(1,0);
    S.dfs2(1);
    int l=S.cnt;
    rep(i,1,l-2) f[i]=c[i+1];
    sort(f+1,f+l-2+1,cmp);
    cnt=0;
    rep(i,2,l-1)
    {
      if (c[i].b>=3) cnt+=c[i].b-2;
      if (c[i].kk)
      {
          if (c[i].b>=1&&i!=(l-1))
          {
            int k1=c[i].a+c[i].b-1,k2=pos2(i+1);
            if (pos(k1+1)<pos(k2+1)) cnt++;
        }
        if (c[i].b>=2)
        {
          int k1=c[i].a+c[i].b-2,k2=c[i].a+c[i].b-1;
          if (pos(k1+1)<pos(k2+1)) cnt++;
        }
      } else
      {
          if (c[i].b>=1&&i!=(l-1))
          {
              int k1=c[i].a,k2=pos2(i+1);
              if (pos(k1+1)<pos(k2+1)) cnt++;
        }
          if (c[i].b>=2)
          {
              int k1=c[i].a+c[i].b-1,k2=c[i].a+c[i].b-2;
              if (pos(k1+1)<pos(k2+1)) cnt++;
          }
      }
    }
    cout<<fsp(2,cnt)<<endl;
    return 0;
}
View Code

 

posted @ 2018-12-25 21:39  尹吴潇  阅读(211)  评论(0编辑  收藏  举报