题目
Description
Input
第一行包含正整数n,表示需要排序的物品数量。
第二行包含n个空格分隔的整数ai,表示每个物品的高度。
Output
输出一行包含n个空格分隔的整数pi。
Sample Input
输入1:
6
3 4 5 1 6 2
输入2:
4
3 3 2 1
Sample Output
输出1:
4 6 4 5 6 6
输出2:
4 2 4 4
Data Constraint
对于30%的数据 1<=n<1000
对于100%的数据 1<=n<=100000 ,1<=ai<=2,000,000,000
题解
看到区间翻转就考虑到splay
其实这就是一道splay区间翻转的裸体
具体的操作都和文艺平衡树差不多,但是相较而言稍微复杂一点
需要注意的是在做findnum操作时要先pushdown一下整条路径,而不是边往根节点走边pushdown,然后仔细阅读题目后发现“相对位置不发生改变”,所以我们可以把所有的输入按照双关键字排序以确定把它们移到前面的顺序
贴代码
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
const int maxn=100005;
int data[maxn],father[maxn],cnt[maxn],lazy[maxn];
int a[maxn][4];
int son[maxn][4];
int i,j,k,l,n,m,t1,t2,root,x,y;
void qsort(int l,int r){
int i,j,mid,mid1;
i=l; j=r; mid=a[(l+r)/2][1]; mid1=a[(l+r)/2][2];
while (i<=j){
while ((a[i][1]<mid)||((a[i][1]==mid)&&(a[i][2]<mid1))) i++;
while ((a[j][1]>mid)||((a[j][1]==mid)&&(a[j][2]>mid1))) j--;
if (i<=j){
a[0][1]=a[i][1]; a[i][1]=a[j][1]; a[j][1]=a[0][1];
a[0][2]=a[i][2]; a[i][2]=a[j][2]; a[j][2]=a[0][2];
i++;
j--;
}
}
if (i<r) qsort(i,r);
if (l<j) qsort(l,j);
}
void pushdown(int x){
int y;
if (!lazy[x]) return;
y=son[x][1]; son[x][1]=son[x][2]; son[x][2]=y;
if (son[x][1]) lazy[son[x][1]]^=1;
if (son[x][2]) lazy[son[x][2]]^=1;
lazy[x]=0;
}
void rotate(int x,int w){
int y;
y=father[x];
cnt[y]=cnt[y]-cnt[x]+cnt[son[x][w]];
cnt[x]=cnt[x]+cnt[y]-cnt[son[x][w]];
father[x]=father[y];
if (father[y]){
if (son[father[y]][1]==y) son[father[y]][1]=x; else son[father[y]][2]=x;
}
son[y][3-w]=son[x][w];
if (son[x][w]) father[son[x][w]]=y;
father[y]=x; son[x][w]=y;
}
void splay(int x){
int y;
pushdown(x);
while (father[x]){
y=father[x];
if (!father[y]) pushdown(father[y]);
pushdown(y);
pushdown(x);
if (y==root){
if (son[y][1]==x) rotate(x,2); else rotate(x,1);
} else{
if (y==son[father[y]][1]){
if (son[y][1]==x) {rotate(y,2); rotate(x,2);}
else{rotate(x,1); rotate(x,2);}
} else{
if (son[y][1]==x){rotate(x,2); rotate(x,1);}
else{rotate(y,1); rotate(x,1);}
}
}
}
root=x;
}
int kth(int x,int w){
int i;
int tmp;
tmp=x;
i=root;
pushdown(i);
while ((x!=cnt[son[i][w]]+1) && (i)){
if (x<cnt[son[i][w]]+1) i=son[i][w]; else{
x=x-cnt[son[i][w]]-1;
i=son[i][3-w];
}
pushdown(i);
}
splay(i);
return i;
}
void dfs(int x){
if (father[x])
dfs(father[x]);
pushdown(x);
}
int findnum(int x){
int ans;
//pushdown(x);
ans=cnt[son[x][1]];
while (father[x]) {
//pushdown(father[x]);
if (son[father[x]][2]==x) ans+=cnt[son[father[x]][1]]+1;
x=father[x];
}
return ans;
}
int main(){
//freopen("3599.in","r",stdin);
//freopen("3599.out","w",stdout);
scanf("%d",&n);
m=n;
for (i=2;i<=n+2;i++){
scanf("%d",&data[i]);
father[i]=i-1;
son[i-1][2]=i;
cnt[i]=n-i+3;
a[i-1][1]=data[i];
a[i-1][2]=i;
}
qsort(1,n);
cnt[1]=n+2;
root=1;
for (i=1;i<=m;i++){
dfs(a[i][2]);
printf("%d ",findnum(a[i][2]));
l=kth(findnum(a[i][2])+2,1);
x=kth(i,1);
father[son[root][2]]=0;
y=cnt[son[root][1]];
root=son[root][2];
//l=findnum(a[i][2])+2;
splay(l);
father[l]=x;
son[x][2]=l;
root=x;
lazy[son[l][1]]^=1;
}
return 0;
}