题解:
我们只需要考虑SA上连续的两个位置能否相等即可。 因为最多只能增加1,设这样的位置个数
,最终答案为
。
我们发现连续的一段很容易判断,用平衡树维护即可。 不连续的地方判断一下位置大小即可。
#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';
}