题意:
设数组 A[i] = i,大小为 n,对其进行 m 次操作,有两种操作:
1. 把某一段提到开头
2. 区间翻转
所有操作结束后询问后缀数组的 rank sa数组为 A 的字符串 S有多少种可能
S 的限制是字符串中出现的都是正整数,且最大元素等于不同的元素个数
n≤109,m≤105
n
≤
10
9
,
m
≤
10
5
题解:
先吐槽,这题调了几天几夜,后来发现原来sa数组。
所以 因为懒 我将sa转成rank来做。
首先splay维护哪个东西。
考虑rank从小到大填入数字,显然,当前填的数字一定大于等于上一位填的数字。
什么时候能相等呢,条件就是
rank[sa[i]+1]<rank[sa[i+1]+1]
r
a
n
k
[
s
a
[
i
]
+
1
]
<
r
a
n
k
[
s
a
[
i
+
1
]
+
1
]
假如在一段连续的区间一定是满足条件的,边界的情况单独处理即可。
code:
#include<map>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int mod=1e9+7;
map<int,int> mp;
struct trnode{
int son[2],fa,l,r,rev,c;
}tr[400010];int tot=0,root;
int L,R,t;
int getnum(int x){return abs(tr[x].r-tr[x].l)+1;}
void update(int x)
{
int lc=tr[x].son[0],rc=tr[x].son[1];
tr[x].c=tr[lc].c+tr[rc].c+getnum(x);
if(tr[x].rev)
{
swap(tr[lc].l,tr[lc].r);swap(tr[rc].l,tr[rc].r);
swap(tr[x].son[0],tr[x].son[1]);
tr[lc].rev^=1;tr[rc].rev^=1;tr[x].rev=0;
}
}
struct node{
int l,r,L,R;
}a[400010],b[400010];int num=0;
void dfs(int x)
{
if(!x) return;
update(x);
dfs(tr[x].son[0]);
b[++num].l=tr[x].l;b[num].r=tr[x].r;
dfs(tr[x].son[1]);
}
void pushup(int x)
{
update(x);
if(tr[x].fa) pushup(tr[x].fa);
}
void pushdown(int x)
{
if(tr[x].fa) pushdown(tr[x].fa);
update(x);
}
void rotate(int x)
{
int y=tr[x].fa,z=tr[y].fa,w,R,r;
w=(tr[y].son[0]==x);
R=y;r=tr[x].son[w];tr[R].son[1-w]=r;if(r) tr[r].fa=R;
R=z;r=x;tr[R].son[tr[z].son[1]==y]=r;tr[r].fa=R;
R=x;r=y;tr[R].son[w]=r;tr[r].fa=R;
update(y);update(x);
}
void splay(int x,int fa)
{
pushdown(x);
while(tr[x].fa!=fa)
{
int y=tr[x].fa,z=tr[y].fa;
if(z==fa) rotate(x);
else
{
if((tr[y].son[0]==x)==(tr[z].son[0]==y)) rotate(y),rotate(x);
else rotate(x),rotate(x);
}
}
if(fa==0) root=x;
}
int find_x(int k)
{
int x=root;t=0;
while(1)
{
update(x);
int lc=tr[x].son[0],rc=tr[x].son[1];
L=t+tr[lc].c+1;R=L+getnum(x)-1;
if(k<=tr[lc].c) x=lc;
else if(k>tr[lc].c+getnum(x)) k-=tr[lc].c+getnum(x),t+=tr[lc].c+getnum(x),x=rc;
else break;
}
L--;R--;
return x;
}
int div_r(int x,int k)
{
if(k==L) return x;
int p=++tot;
if(tr[x].l<=tr[x].r)
{
tr[p].l=tr[x].r-(R-k);tr[p].r=tr[x].r;
tr[x].r=tr[p].l-1;
}
else
{
tr[p].l=tr[x].r+(R-k);tr[p].r=tr[x].r;
tr[x].r=tr[p].l+1;
}
tr[p].son[1]=tr[x].son[1];tr[x].son[1]=0;
tr[p].fa=tr[x].fa;tr[x].fa=p;tr[p].son[0]=x;
tr[tr[p].fa].son[tr[tr[p].fa].son[1]==x]=p;
if(tr[p].son[1]) tr[tr[p].son[1]].fa=p;
update(x);update(p);
if(root==x) root=p;
return p;
}
int div_l(int x,int k)
{
if(k==R) return x;
int p=++tot;
if(tr[x].l<=tr[x].r)
{
tr[p].r=tr[x].l+(k-L);tr[p].l=tr[x].l;
tr[x].l=tr[p].r+1;
}
else
{
tr[p].r=tr[x].l-(k-L);tr[p].l=tr[x].l;
tr[x].l=tr[p].r-1;
}
tr[p].son[0]=tr[x].son[0];tr[x].son[0]=0;
tr[p].fa=tr[x].fa;tr[x].fa=p;tr[p].son[1]=x;
tr[tr[p].fa].son[tr[tr[p].fa].son[1]==x]=p;
if(tr[p].son[0]) tr[tr[p].son[0]].fa=p;
update(x);update(p);
if(root==x) root=p;
return p;
}
void solve(int l,int r)
{
int x=find_x(l);x=div_l(x,l-1);
int y=find_x(r+2);y=div_r(y,r+1);
splay(x,0);splay(y,x);
}
int n,m;
void add(int l,int r,int fa,int d)
{
int x=++tot;
tr[x].l=l;tr[x].r=r;tr[x].fa=fa;
tr[fa].son[d]=x;tr[x].c=r-l+1;
pushup(x);
}
LL pow(LL a,int b)
{
LL ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;b>>=1;
}
return ans;
}
bool cmp(node a,node b) {return a.l<b.l;}
bool cmp_L(node a,node b) {return a.L<b.L;}
int get_next(int k,int x,int op)
{
if(x==n) return 0;
return mp[x+1]?mp[x+1]:k+op;
}
int main()
{
scanf("%d %d",&n,&m);
root=tot=1;tr[1].l=0;tr[1].r=0;tr[1].c=0;
add(n+1,n+1,1,1);add(1,n,2,0);
while(m--)
{
int op,l,r;scanf("%d %d %d",&op,&l,&r);
if(op==1)
{
solve(l,r);
int x=tr[tr[root].son[1]].son[0];
swap(tr[x].l,tr[x].r);tr[x].rev^=1;
}
else
{
if(l!=1)
{
solve(l,r);
int x=tr[tr[root].son[1]].son[0],y=tr[root].son[1];
tr[x].fa=0;tr[y].son[0]=0;pushup(y);
solve(1,1);y=tr[tr[root].son[1]].son[0];
pushdown(y);
tr[y].son[0]=x;tr[x].fa=y;pushup(x);
}
}
}
num=-1;dfs(root);
int now=0,ans=0;
for(int i=1;i<num;i++)
{
now++;int L=now,R=now+abs(b[i].r-b[i].l);now+=abs(b[i].r-b[i].l);
if(b[i].l>b[i].r) swap(b[i].l,b[i].r),swap(L,R);
a[i].l=L;a[i].r=R;a[i].L=b[i].l;a[i].R=b[i].r;
}
sort(a+1,a+num,cmp_L);a[num].l=0;
for(int i=1;i<num;i++)
{
ans+=max(abs(a[i].r-a[i].l)-1,0);
if(abs(a[i].r-a[i].l)>=1)
{
if(a[i].l<a[i].r) ans+=(a[i+1].l>a[i].r);
if(a[i].l>a[i].r) ans+=(a[i+1].l<a[i].r);
}
}
for(int i=1;i<num;i++) mp[a[i].L]=a[i].l,mp[a[i].R]=a[i].r;
sort(a+1,a+num,cmp);
for(int i=1;i<num-1;i++)
{
if(a[i].l<=a[i].r)
{
if(a[i+1].l<=a[i+1].r) ans+=(get_next(a[i+1].l,a[i+1].L,1)>mp[a[i].R+1]);
else ans+=(mp[a[i+1].R+1]>mp[a[i].R+1]);
}
else
{
if(a[i+1].l<=a[i+1].r) ans+=(get_next(a[i+1].l,a[i+1].L,1)>get_next(a[i].l,a[i].L,-1));
else ans+=(mp[a[i+1].R+1]>get_next(a[i].l,a[i].L,-1));
}
}
printf("%lld",pow(2,ans));
}