Codechef : TASUFFIX

传送门

题解:
我们只需要考虑SA上连续的两个位置能否相等即可。 因为最多只能增加1,设这样的位置个数 p ,最终答案为 2 p

我们发现连续的一段很容易判断,用平衡树维护即可。 不连续的地方判断一下位置大小即可。

#include <bits/stdc++.h>
using namespace std;

const int RLEN=1<<18|1;
inline char nc() {
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
    char ch=nc(); int i=0,f=1;
    while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
    return i*f;
}

const int N=4e5+50, mod=1e9+7;
int n,m,cnt;
inline int mul(int a,int b) {return (long long)a*b%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}
struct node {
    node *lc,*rc;
    int rev_tag,rev_all,l,r,sze;
    int pri;
    node() {pri=(rand()<<15)^rand();}
    inline void rev() {swap(lc,rc); rev_tag^=1; rev_all^=1;}
    inline void upt() {sze=lc->sze+rc->sze+r-l+1;}
    inline void pushdown() {
        if(rev_tag) {
            lc->rev();
            rc->rev();
            rev_tag=0;
        }
    }
} Pool[N],*pool=Pool,*null=Pool,*rt;
typedef pair <node*,node*> pii;
inline node* newnode(int rev_all,int l,int r) {
    node *t=++pool;
    t->lc=t->rc=null;
    t->l=l; t->r=r; t->rev_all=rev_all;
    t->upt(); return t;
}
inline node* merge(node *x,node *y) {
    if(x==null) return y;
    if(y==null) return x;
    x->pushdown(); y->pushdown();
    if(x->pri>y->pri) {
        x->rc=merge(x->rc,y);
        x->upt(); return x;
    } else {
        y->lc=merge(x,y->lc);
        y->upt(); return y;
    }
}
inline pii split(node *x,int t) {
    if(x==null) return pii(null,null);
    x->pushdown();
    if(x->lc->sze+x->r-x->l+1<=t) {
        pii tr=split(x->rc,t-x->lc->sze-x->r+x->l-1);
        x->rc=tr.first; x->upt();
        return pii(x,tr.second);
    } else {
        pii tr=split(x->lc,t);
        x->lc=tr.second; x->upt();
        return pii(tr.first,x);
    }
}
inline pii splitL(node *x) {
    x->pushdown();
    if(x->lc==null) {
        pii tr=pii(x,x->rc);
        x->rc=null; x->upt();
        return tr;
    } else {
        pii tr=splitL(x->lc);
        x->lc=tr.second; x->upt();
        return pii(tr.first,x);
    }
}
inline void split(int t) {
    pii tr=split(rt,t-1); 
    if(tr.first->sze==t-1) {
        rt=merge(tr.first,tr.second);
        return;
    }
    pii tr2=splitL(tr.second);
    int l=tr2.first->l, r=tr2.first->r, res=t-tr.first->sze-1;
    if(tr2.first->rev_all) {
        node *t1=newnode(1,r-res+1,r);
        node *t2=newnode(1,l,r-res);
        tr2.first=merge(t1,t2);
        rt=merge(tr.first,merge(tr2.first,tr2.second));
    } else {
        node *t1=newnode(0,l,l+res-1);
        node *t2=newnode(0,l+res,r);
        tr2.first=merge(t1,t2);
        rt=merge(tr.first,merge(tr2.first,tr2.second));
    }
}

typedef pair <node*,int> pni;
typedef vector < pair <int,pni> > :: iterator it_s;
vector <pair <int,pni> > S;
node* stk[N];
inline void dfs(node *x) {
    if(x==null) return;
    x->pushdown();
    dfs(x->lc);
    S.push_back(make_pair(x->l,pni(x,++cnt))); 
    stk[cnt]=x;
    dfs(x->rc);
}
inline bool operator <(const pair <int,pni> &a,const pair <int,pni> &b) {return a.first<b.first;}
inline bool operator <(const pair <int,pni> &a,const int &b) {return a.first<b;}
inline bool operator <(const int &a,const pair <int,pni> &b) {return a<b.first;}
inline bool judge(int x,int y) {
    if(x>n || !x) return true;
    if(y>n || !y) return false;
    it_s xx=--upper_bound(S.begin(),S.end(),x), yy=--upper_bound(S.begin(),S.end(),y);
    if(xx->second.second^yy->second.second) return xx->second.second<yy->second.second;
    return (x<y) ^ (xx->second.first->rev_all);
}
int main() { 
    n=rd(), m=rd(); rt=newnode(0,1,n);
    for(int i=1;i<=m;i++) {
        int op=rd(),l=rd(), r=rd();
        split(l); 
        split(r+1);
        if(op==1) {
            pii tr=split(rt,r);
            pii tr2=split(tr.first,l-1);
            tr2.second->rev();
            rt=merge(merge(tr2.first,tr2.second),tr.second);
        } else {
            pii tr=split(rt,r);
            pii tr2=split(tr.first,l-1);
            rt=merge(tr2.second,merge(tr2.first,tr.second));
        }
    } 
    dfs(rt); int p=0;
    sort(S.begin(),S.end());
    for(int i=1;i<=cnt;++i) {
        node *t=stk[i];
        node *sf=(i==cnt ? null : stk[i+1]);
        int suf=(sf->rev_all ? sf->r : sf->l);
        p+=t->r-t->l-(t->r>t->l);
        if(t->rev_all) {
            if(suf && judge(t->l+1,suf+1)) ++p;
            if(t->l!=t->r && judge(t->r+1,t->r)) ++p;
        } else {
            if(suf && judge(t->r+1,suf+1)) ++p;
            if(t->l!=t->r && judge(t->r,t->r+1)) ++p;
        }
    } cout<<power(2,p)<<'\n';
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/80905307