转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
对区间有反转,同样用懒惰标记,SPT比较方便。
依次考虑第K大的,将其旋转至根,左子树的数量便是需要反转的,之后把根删除即可
难道是我的伸展函数有问题,一直TLE,注释部分的求大神解释。
换了一个Splay函数就过了。。。郁闷啊,debug到死
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 100015
#define inf 1<<29
#define LL long long
#define Key_value ch[ch[root][1]][0]
using namespace std;
int pre[N],ch[N][2],root,tot1; //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
int size[N]; //分别表示子树规模,内存池,内存池容量
int rev[N];
int n,q;
inline void NewNode(int &r,int father,int k){
r=k;
pre[r]=father;
rev[r]=0;
size[r]=1;
ch[r][0]=ch[r][1]=0; //左右孩子为空
}
//将延迟标记更新到孩子结点
inline void Push_Down(int r){
if(rev[r]){
rev[ch[r][0]]^=1;
rev[ch[r][1]]^=1;
swap(ch[r][0],ch[r][1]);
rev[r]=0;
}
}
//通过孩子结点更新父结点
inline void Push_Up(int r){
size[r]=size[ch[r][0]]+size[ch[r][1]]+1;
}
//旋转,kind为1为右旋,kind为0为左旋
inline void Rotate(int x,int kind){
int y=pre[x];
Push_Down(y);
Push_Down(x);
//类似SBT,要把其中一个分支先给父节点
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
//如果父节点不是根结点,则要和父节点的父节点连接起来
pre[x]=pre[y];
if(pre[x])
ch[pre[y]][ch[pre[y]][1]==y]=x;
ch[x][kind]=y;
pre[y]=x;
Push_Up(y);
}inline void zig(int x){
int y=pre[x], z=pre[y];
ch[y][1]=ch[x][0]; pre[ch[x][0]]=y;
ch[x][0]=y; pre[y]=x;
pre[x]=z;
if(z) ch[z][ch[z][1]==y]=x;
Push_Up(y);
}
inline void zag(int x){
int y=pre[x], z=pre[y];
ch[y][0]=ch[x][1]; pre[ch[x][1]]=y;
ch[x][1]=y; pre[y]=x;
pre[x]=z;
if(z) ch[z][ch[z][1]==y]=x;
Push_Up(y);
}
inline void zigzig(int x){
int y=pre[x], z=pre[y], fz=pre[z];
ch[z][1]=ch[y][0]; pre[ch[y][0]]=z;
ch[y][1]=ch[x][0]; pre[ch[x][0]]=y;
pre[z]=y; ch[y][0]=z;
pre[y]=x; ch[x][0]=y;
pre[x]=fz;
if(fz) ch[fz][ch[fz][1]==z]=x;
Push_Up(z); Push_Up(y);
}
inline void zagzag(int x){
int y=pre[x], z=pre[y], fz=pre[z];
ch[z][0]=ch[y][1]; pre[ch[y][1]]=z;
ch[y][0]=ch[x][1]; pre[ch[x][1]]=y;
pre[z]=y; ch[y][1]=z;
pre[y]=x; ch[x][1]=y;
pre[x]=fz;
if(fz) ch[fz][ch[fz][1]==z]=x;
Push_Up(z); Push_Up(y);
}
inline void zigzag(int x){
int y=pre[x], z=pre[y], fz=pre[z];
ch[y][1]=ch[x][0]; pre[ch[x][0]]=y;
ch[z][0]=ch[x][1]; pre[ch[x][1]]=z;
pre[y]=pre[z]=x;
ch[x][0]=y; ch[x][1]=z;
pre[x]=fz;
if(fz) ch[fz][ch[fz][1]==z]=x;
Push_Up(z); Push_Up(y);
}
inline void zagzig(int x){
int y=pre[x], z=pre[y], fz=pre[z];
ch[y][0]=ch[x][1]; pre[ch[x][1]]=y;
ch[z][1]=ch[x][0]; pre[ch[x][0]]=z;
pre[y]=pre[z]=x;
ch[x][1]=y; ch[x][0]=z;
pre[x]=fz;
if(fz) ch[fz][ch[fz][1]==z]=x;
Push_Up(z); Push_Up(y);
}
void Splay(int x, int goal){
int y, z;
Push_Down(x);
while(pre[x]!=goal){
if(pre[pre[x]]==goal){
y=pre[x]; Push_Down(y); Push_Down(x);
if(ch[y][1]==x) zig(x);
else zag(x);
}
else{
y=pre[x]; z=pre[y];
Push_Down(z); Push_Down(y); Push_Down(x);
if(ch[z][1]==y){
if(ch[y][1]==x) zigzig(x);
else zagzig(x);
}
else{
if(ch[y][0]==x) zagzag(x);
else zigzag(x);
}
}
}
Push_Up(x);
if(pre[x]==0) root=x;
}
//Splay调整,将根为r的子树调整为goal
/*inline void Splay(int r,int goal){
Push_Down(r);
while(pre[r]!=goal){
//父节点即是目标位置,goal为0表示,父节点就是根结点
if(pre[pre[r]]==goal)
Rotate(r,ch[pre[r]][0]==r);
else{
int y=pre[r];
int kind=(ch[pre[y]][0]==y);
//两个方向不同,则先左旋再右旋
if(ch[y][kind]==r){
Rotate(r,!kind);
Rotate(r,kind);
}
//两个方向相同,相同方向连续两次
else{
Rotate(y,kind);
Rotate(r,kind);
}
}
}
Push_Up(r);
//更新根结点
if(goal==0) root=r;
}
*/
inline int Get_Max(int r){
Push_Down(r);
while(ch[r][1]){
r=ch[r][1];
Push_Down(r);
}
return r;
}
inline void Remove(){ // erase the root
if(ch[root][0]==0){
root=ch[root][1];
pre[root]=0;
}
else{
int m=Get_Max(ch[root][0]);
Splay(m,root);
ch[m][1]=ch[root][1];
pre[ch[root][1]]=m;
root=m;
pre[root]=0;
Push_Up(root);
}
}
inline void BulidTree(int &x,int l,int r,int father){
if(l>r)
return;
int mid=(l+r)>>1;
NewNode(x,father,mid);
BulidTree(ch[x][0],l,mid-1,x);
BulidTree(ch[x][1],mid+1,r,x);
Push_Up(x);
}
struct Node{
int idx,num;
}a[N];
inline bool cmp(Node n1,Node n2){
return n1.num!=n2.num?n1.num<n2.num:n1.idx<n2.idx;
}
inline void Init(){
for(int i=1;i<=n;i++){
scanf("%d",&a[i].num);
a[i].idx=i;
}
sort(a+1,a+1+n,cmp);
ch[0][0]=ch[0][1]=pre[0]=size[0]=rev[0]=0;
root=tot1=0;
BulidTree(root,1,n,0);
}
int main(){
while(scanf("%d",&n)!=EOF&&n){
Init();
for(int i=1;i<n;i++){
Splay(a[i].idx,0);
rev[ch[root][0]]^=1;
printf("%d ",i+size[ch[root][0]]);
Remove();
}
printf("%d\n",n);
}
return 0;
}