当前位置: 代码迷 >> 综合 >> bzoj2209(splay)
  详细解决方案

bzoj2209(splay)

热度:38   发布时间:2024-01-04 12:48:05.0

debug很爽,表示细节错误一个有一个。

注意:1:在更新打标记时,要把原始数据和维护数据一起更新!!

2:在序列问题中,查找一个数只能用size找排名来找,因为,序列可能翻转!!

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;
const int N=100005;int n,m,a[N];
char s[N];int fa[N],ch[N][2],rev[N],fz[N],rt,mxl[N],mxr[N],mil[N],mir[N],sum[N],size[N];void up(int i)
{int l=ch[i][0],r=ch[i][1];size[i]=size[l]+size[r]+1;sum[i]=sum[l]+sum[r]+a[i];mxl[i]=max(0,max(sum[l]+a[i]+mxl[r],mxl[l]));mxr[i]=max(0,max(sum[r]+a[i]+mxr[l],mxr[r]));mil[i]=min(0,min(sum[l]+a[i]+mil[r],mil[l]));mir[i]=min(0,min(sum[r]+a[i]+mir[l],mir[r]));
}int build(int fat,int l,int r)
{if (l>r) return 0;int mid=(l+r)>>1;fa[mid]=fat;size[mid]=1;ch[mid][0]=build(mid,l,mid-1);ch[mid][1]=build(mid,mid+1,r);up(mid);return mid;
}
void down(int i)
{int pos,l=ch[i][0],r=ch[i][1];if (fz[i]){fz[i]^=1,fz[l]^=1,fz[r]^=1;sum[l]=-sum[l],sum[r]=-sum[r];for (int j=0;j<=1;j++){pos=ch[i][j];a[pos]=-a[pos];swap(mxl[pos],mil[pos]);mxl[pos]=-mxl[pos];mil[pos]=-mil[pos];swap(mxr[pos],mir[pos]);mxr[pos]=-mxr[pos];mir[pos]=-mir[pos];		}}if (rev[i]){rev[i]^=1,rev[l]^=1,rev[r]^=1;swap(ch[i][0],ch[i][1]);swap(mxl[l],mxr[l]);swap(mil[l],mir[l]);swap(mxl[r],mxr[r]);swap(mil[r],mir[r]);}
}
stack<int> ss;
void rotate(int x)  
{  int y=fa[x],z=fa[y],l,r;  if (ch[y][0]==x) l=0;else l=1;r=l^1;  if (z) if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;  fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;  ch[y][l]=ch[x][r];ch[x][r]=y; up(y); 
}  
void splay(int x,int k)  
{  int y,z;  while (fa[x]!=k)  {  y=fa[x];z=fa[y];  if (z!=k)  {  if ((ch[z][0]==y)^(ch[y][0]==x)) rotate(x);else rotate(y);  }  rotate(x);  }  if (k==0) rt=x;up(x); 
}  
int find_kth(int u,int k)//必须用名次查找位置!!!
{down(u);if (size[ch[u][0]]+1==k) return u;if (size[ch[u][0]]>=k) return find_kth(ch[u][0],k);return find_kth(ch[u][1],k-size[ch[u][0]]-1);
}
int split(int x,int y)
{int posx=find_kth(rt,x-1);splay(posx,0);int posy=find_kth(rt,y+1);splay(posy,posx);return ch[posy][0];
}
inline int read()
{int ans;char ch;while ((ch=getchar())<'0'||ch>'9');ans=ch-'0';while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';return ans;
}
int main()
{n=read(),m=read();scanf("%s",s+1);for (int i=2;i<=n+1;i++) if (s[i-1]=='(') a[i]=1;else a[i]=-1;a[1]=a[n+2]=0;rt=build(0,1,n+2);int t,x,y,pos;for (int i=1;i<=m;i++){t=read(),x=read(),y=read();x++,y++;pos=split(x,y);switch(t){case 0:printf("%d\n",-(mil[pos]-1)/2+(mxr[pos]+1)/2);break;case 1:fz[pos]^=1;a[pos]=-a[pos];//注意把原始数据更新!!查了好长时间sum[pos]=-sum[pos];swap(mxl[pos],mil[pos]);mxl[pos]=-mxl[pos];mil[pos]=-mil[pos];swap(mxr[pos],mir[pos]);mxr[pos]=-mxr[pos];mir[pos]=-mir[pos];up(fa[pos]);up(rt);break;case 2:rev[pos]^=1;swap(mxl[pos],mxr[pos]);swap(mil[pos],mir[pos]);up(fa[pos]),up(rt);break;}}return 0;
}