版权声明:这是蒟蒻的BLOG,神犇转载也要吱一声哦~ https://blog.csdn.net/Dream_Lolita/article/details/89260467
【题目】
CC
给定一个长度为 的 数组,有两种操作:
- 翻转一段区间
- 将一段区间移动到开头
求有多少个本质不同的字符串符合最后得到的 ,字符串本质不同的意思是不存在一种方式重标号(相同字符标号一样)后两个字符串相同。
【解题思路】
第一眼,
怎么这么大,神题吧。
第二眼,还要动态维护操作,神题吧。
还有
表示的是排名为
的字符串是第
个这玩意坑了我挺久来着。
茫茫久后,发现只需要最后输出答案。而答案实际上就是若
和
的位置两个字符可以相同则有
的乘积贡献。
也就是说,若
,则
有贡献,这个可以用个
什么的实现判断,反正巨麻烦。
一段
连续的序列答案很容易求,因此我们只需要考虑不连续的位置。
由于
很大,但
比较小,还要支持翻转和移动,我们考虑用平衡树维护这个东西。
维护方式显然就是初始一个点代表一个区间,每次操作最多将两个区间拆分,平衡树上每个点维护一下代表的区间和是否翻转之类的就可以了。
最后可用一个一个节点考虑答案,平衡树使用
或
这类可提出区间的即可。
复杂度
,细节还是很多的(心累)。
最后吐槽一下,数据太水了,我一个本该完全错的代码竟然能过。
所以大家写这个题目就算交过了,但最好多拿几个代码对拍一下吧。
【参考代码】
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10,mod=1e9+7;
int read()
{
int ret=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return ret;
}
namespace Data_Structure
{
int rt,nowl,nowr;
struct Splay
{
#define ls ch[x][0]
#define rs ch[x][1]
int sz;
int L[N],R[N],rev[N],fa[N],siz[N],ch[N][2];
int glen(int x){return abs(R[x]-L[x])+1;}
void rever(int x){swap(L[x],R[x]);rev[x]^=1;}
void pushup(int x){siz[x]=siz[ls]+siz[rs]+glen(x);}
void pushdown(int x){if(rev[x]) swap(ls,rs),rever(ls),rever(rs),rev[x]=0;}
int get(int x){return ch[fa[x]][1]==x;}
void rotate(int x)
{
int y=fa[x],z=fa[y],k=get(x);
if(z) ch[z][get(y)]=x;
fa[ch[x][!k]]=y;fa[y]=x;fa[x]=z;
ch[y][k]=ch[x][!k];ch[x][!k]=y;
pushup(y);pushup(x);
}
void splay(int x,int goal)
{
while(fa[x]!=goal)
{
int y=fa[x];
if(fa[y]!=goal) rotate(get(y)==get(x)?y:x);
rotate(x);
}
if(!goal) rt=x;
}
int findx(int k)
{
int x=rt,t=0;
while(1)
{
pushdown(x);
nowl=t+siz[ls]+1;nowr=nowl+glen(x)-1;
if(k<=siz[ls]) x=ls;
else if(k>siz[ls]+glen(x)) k-=siz[ls]+glen(x),t+=siz[ls]+glen(x),x=rs;
else break;
}
--nowl;--nowr;
return x;
}
int divr(int x,int k)
{
if(k==nowl) return x;
int p=++sz;
if(L[x]<=R[x])
{
L[p]=R[x]-(nowr-k);R[p]=R[x];
R[x]=L[p]-1;
}
else
{
L[p]=R[x]+(nowr-k);R[p]=R[x];
R[x]=L[p]+1;
}
ch[p][1]=rs;rs=0;
fa[p]=fa[x];fa[x]=p;ch[p][0]=x;
ch[fa[p]][ch[fa[p]][1]==x]=p;
if(ch[p][1]) fa[ch[p][1]]=p;
pushup(x);pushup(p);
if(rt==x) rt=p;
return p;
}
int divl(int x,int k)
{
if(k==nowr) return x;
int p=++sz;
if(L[x]<=R[x])
{
R[p]=L[x]+(k-nowl);L[p]=L[x];
L[x]=R[p]+1;
}
else
{
R[p]=L[x]-(k-nowl);L[p]=L[x];
L[x]=R[p]-1;
}
ch[p][0]=ls;ls=0;
fa[p]=fa[x];fa[x]=p;ch[p][1]=x;
ch[fa[p]][ch[fa[p]][1]==x]=p;
if(ch[p][0]) fa[ch[p][0]]=p;
pushup(x);pushup(p);
if(rt==x) rt=p;
return p;
}
void solve(int l,int r)
{
int x=findx(l);x=divl(x,l-1);
int y=findx(r+2);y=divr(y,r+1);
splay(x,0);splay(y,x);
}
void add(int l,int r,int f,int d)
{
int x=++sz;
L[x]=l;R[x]=r;fa[x]=f;
ch[f][d]=x;siz[x]=r-l+1;
pushup(x);pushup(f);
}
#undef ls
#undef rs
}T;
}
using namespace Data_Structure;
namespace DreamLolita
{
int n,Q,cnt;
int L[N],R[N];
map<int,int>mp;
struct data
{
int l,r,L,R;
}a[N];
bool cmpl(const data&a,const data&b){return a.l<b.l;}
bool cmpL(const data&a,const data&b){return a.L<b.L;}
int gnex(int k,int x,int op)
{
if(x==n) return 0;
return mp[x+1]?mp[x+1]:k+op;
}
int qpow(int x,int y){int res=1;for(;y;y>>=1,x=1ll*x*x%mod)if(y&1)res=1ll*res*x%mod;return res;}
void dfs(int x)
{
if(!x) return; T.pushdown(x);
dfs(T.ch[x][0]);L[++cnt]=T.L[x];R[cnt]=T.R[x];dfs(T.ch[x][1]);
}
void solution()
{
n=read();Q=read();
rt=T.sz=1;
T.add(n+1,n+1,1,1);T.add(1,n,2,0);
while(Q--)
{
int op=read(),l=read(),r=read();
if(op&1) T.solve(l,r),T.rever(T.ch[T.ch[rt][1]][0]);
else
{
if(l^1)
{
T.solve(l,r);
int x=T.ch[T.ch[rt][1]][0],y=T.ch[rt][1];
T.pushdown(y);T.fa[x]=0;T.ch[y][0]=0;T.pushup(y);
T.solve(1,1);y=T.ch[T.ch[rt][1]][0];
T.pushdown(y);T.ch[y][0]=x;T.fa[x]=y;T.pushup(y);
}
}
}
cnt=-1;dfs(rt);
int now=0,ans=0;
for(int i=1;i<cnt;++i)
{
//printf("%d %d\n",L[i],R[i]);
++now;int l=now,r=now+abs(R[i]-L[i]);now+=abs(R[i]-L[i]);
if(L[i]>R[i]) swap(L[i],R[i]),swap(l,r);
a[i].l=l;a[i].r=r;a[i].L=L[i];a[i].R=R[i];
}
sort(a+1,a+cnt,cmpL);a[cnt].l=0;
for(int i=1;i<cnt;++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<cnt;++i) mp[a[i].L]=a[i].l,mp[a[i].R]=a[i].r;
sort(a+1,a+cnt,cmpl);
for(int i=1;i<cnt-1;++i)
{
if(a[i].l<=a[i].r)
{
if(a[i+1].l<=a[i+1].r) ans+=(gnex(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+=(gnex(a[i+1].l,a[i+1].L,1)>gnex(a[i].l,a[i].L,-1));
else ans+=(mp[a[i+1].R+1]>gnex(a[i].l,a[i].L,-1));
}
}
printf("%d\n",qpow(2,ans));
}
}
int main()
{
#ifdef Durant_Lee
freopen("CC_TASUFFIX.in","r",stdin);
freopen("CC_TASUFFIX.out","w",stdout);
#endif
DreamLolita::solution();
return 0;
}