為了把工廠中高低不等的物品按從低到高排好序,工程師發明了一種排序機械臂。它遵循乙個簡單的排序規則,第一次操作找到最低的物品位置 p1,並把從左起第 1 個至第 p1 個之間的物品反序;第二次找到第二低的物品的位置 p2,並把左起第二個至第 p2 個之間的物品反序……最終所有的物品都會被排好序。
上圖給出乙個示例,第一次操作前,最低物品在位置 4,於是把第 1 至第 4 個物品反序;第二次操作前,第二低的物品在位置 6,於是把第 2 至第 6 的物品反序……
你的任務是編寫乙個程式,確定操作序列,即每次操作前第 i 低的物品所在的位置pi,以便機械臂工作。需要注意的是,如果有高度相同的物品,必須保證排序後他們的相對位置關係與初始時相同。
第一行包含乙個正整數 n,表示需要排序的物品數量。
第二行包含 n 和空格分隔的整數 ai,表示每個物品的高度。
輸出一行包含 n 個空格分隔的整數 pi。
輸入 [複製]
6輸出3 4 5 1 6 2
4 6 4 5 6 6
輸入 [複製]
4輸出3 3 2 1
4 2 4 4
【資料範圍】
對於 30% 的資料:1≤n≤1000
對於 100% 的資料:1≤n≤100000,1≤ai≤2×109
利用splay進行區間反轉模版題:若要反轉i-j內的區間(包括i,j)先找到下標為i-1的點splay到根節點,再找到j+1的點splay到i-1下方,將j+1的左子樹的子樹進行swap即可(注意打標記)
#include#include#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
const
int n=100005
;int father[n],son[n][2
],tag[n],size[n],root,tot,num[n];
intn,rank[n];
struct
node
a[n];
intr()
bool
cmp(node a,node b)
inline
void pushdown(int
now)
}inline
void update(int
now)
}inline
intget(int
now)
inline
void rotate(int
now)
inline
void splay(int now,int
to)
if(!to) root=now;
}inline
void insert(int
x)
last=now;
now=son[now][1
]; }
}inline
int find(int
x) x-=temp;now=son[now][1
]; }
}}intmain()
return0;
}
排序機械臂 splay
給定乙個長度為n的序列,需要進行n次交換操作.第i次操作需要將區間 i,pi 進行翻轉,其中pi表示序列第i小的數字的下標.特別的,如果序列中有重複的元素,則認為在初始序列中下標小的數字更小.題目中由於涉及到了區間翻轉,我們應當聯想到是否可以採用 平衡樹 解決該問題.首先有個疑問,我們應當如何維護序...
CQOI2014 排序機械臂
題目鏈結 洛谷 p3165 bzoj 3506 解析 如果用 splay 做,需要先排序,記錄每個點被選中的順序。考慮到 fhq treap 的 heap 性質,直接將結點的 key 值設為每個物品的高度。充分利用小根堆的性質,使每次被選中的結點一定是根結點。當資料單調時,操作總複雜度為 o n 但...
CQOI2014 排序機械臂
一道很水很水的題,splay樹儲存乙個最小值,每次查詢最小值所在的位置,旋轉到根,輸出它在第幾位。然後將它之前的節點打上翻轉標記,維護一下即可。注意這道題要先排序,因為翻轉操作之後就不知到它原來的位置了。1 never forget why you start 2 include3 include4...