题目大意:
给定一个n元素数列,n次操作,第i次要求输出第i小的数的当前位置t,再将区间[i,t]翻转
【题解】
模板题,记录伸展树中 以每个结点为根的子树的最小值,通过它在logN时间内找到最小值的位置,
然后提取出序列并打上翻转标记,
每次操作结束,将最左边的元素分裂出去,这样每次操作都是找最小值
本题有重复元素,有些麻烦,但题目只让给出位置,可以先离散化去重再处理
【代码】
#include
#include
#define INF 1000000
int a[100005],b[100005];
struct Node
{
Node* ch[2];
int v,s,f,Min;
int cmp(int x) const
{
if(x==ch[0]->s+1) return -1;
if(x<=ch[0]->s) return 0;
return 1;
}
};
Node *root,*null,*left,*right;
int min(int a,int b)
{
if(ach[0]=null->ch[1]=NULL;
null->v=null->s=null->f=0;
null->Min=INF;
root=left=right=null;
}
void wh(Node* &o)
{
o->Min = min( o->v , min(o->ch[0]->Min,o->ch[1]->Min) );
o->s = o->ch[0]->s + 1 + o->ch[1]->s;
}
void pushdown(Node* &o)
{
if(o->f==0) return;
Node* t=o->ch[0];
o->ch[0]=o->ch[1];
o->ch[1]=t;
o->f=0;
o->ch[0]->f^=1;
o->ch[1]->f^=1;
}
void build(Node* &o,int left,int right)
{
int mid=(left+right)/2;
o=new Node();
o->ch[0]=o->ch[1]=null;
o->v=a[mid];
o->f=0;
if(leftch[0],left,mid-1);
if(right>mid) build(o->ch[1],mid+1,right);
wh(o);
}
void xz(Node* &o,int d)
{
Node* k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
wh(o);
wh(k);
o=k;
}
void splay(Node* &o,int k)
{
pushdown(o);
int d=o->cmp(k),d2,k2;
if(d==1) k -= o->ch[0]->s + 1;
if(d!=-1)
{
Node* p=o->ch[d];
pushdown(p);
k2=k;
d2=p->cmp(k2);
if(d2==1) k2 -= p->ch[0]->s + 1;
if(d2!=-1)
{
splay(p->ch[d2],k2);
if(d==d2) xz(o,d^1);
else xz(o->ch[d],d2^1);
}
xz(o,d^1);
}
}
void fl(Node* &o,int k,Node* &left,Node* &right)
{
splay(o,k);
right=o->ch[1];
o->ch[1]=null;
left=o;
wh(left);
}
Node* hb(Node* &left,Node* &right)
{
splay(left,left->s);
left->ch[1]=right;
wh(left);
return left;
}
int cx(Node* &o)
{
pushdown(o);
if( o->v < min(o->ch[0]->Min,o->ch[1]->Min) ) return o->ch[0]->s+1;
if( o->ch[0]->Min < o->ch[1]->Min ) return cx(o->ch[0]);
return o->ch[0]->s + 1 + cx(o->ch[1]);
}
void kp(int low,int high)
{
int i=low,j=high,mida=a[(i+j)/2],midb=b[(i+j)/2];
while(imida||(a[j]==mida&&b[j]>midb)) j--;
if(i<=j)
{
jh(&a[i],&a[j]);
jh(&b[i],&b[j]);
i++;
j--;
}
}
if(j>low) kp(low,j);
if(if^=1;
root=hb(left,right);
fl(root,1,left,right);
root=right;
}
return 0;
}