CERC2007 機器排序

2022-05-08 04:27:09 字數 3484 閱讀 5462

在布拉格捷克理工大學(czech technical university)某個幽深的角落,有一些實驗室用來檢測各種材料的機械和電氣效能。在昨天的一項展示中,你已經見識了其中的一間是如何變成全新的多 **實驗室的。但那裡仍然有別的實驗室,服務於它們最初的用途。

在這個任務中,你將要給這樣的一間實驗室中乙個搬運樣品的機械人編寫程式。設想有一些材料樣品在一條傳送帶上排成一排。這些樣品有不同的高度,這可能會給接下來的處理帶來麻煩。為了消除這樣的隱患,我們需要將這些樣品按高度公升序排列。

排序由一條機械臂完成,它可以抱起一些連續的樣品並且將它們掉頭,這樣一來它們在傳送帶上的順序就被翻轉。換句話說,乙個操作可以翻轉a到b(含兩端)的樣品順序。

給樣品排序的乙個可能方式是找到高度最小的樣品p1,將1到p1的樣品順序翻轉。這將使得p1成為第乙個樣品。接下來我們找到高度第二小的樣品p2,將2到p2的樣品順序翻轉。然後找到高度第三小的樣品,以此類推。

這張展示了乙個含6個樣品的簡單例子。高度最小的樣品在4號位置,因此機械臂旋轉前4個樣品。高度第二小的樣品在6號位置,因此下乙個操作是翻轉2-6號樣品位置。第三步是翻轉3-4號樣品位置,以此類推。

你的任務是找到用上述演算法給樣品排序時正確的翻轉操作序列。如果不止乙個樣品有相同的高度,必須保持它們的順序不變:在初始序列中靠前的在最終序列中也應該靠前。

輸入包含多組資料。

每組資料有兩行。第一行是乙個正整數n,即樣品個數(1<=n<=100000)。

第二行有n個由空格分隔的正整數,即各樣品的高度,按最初的樣品順序給出。

輸入結束標誌為一行乙個0。

對每組資料,輸出一行恰好n個整數p1,p2,...,pn,彼此由空格分隔。每個pi應該是乙個正整數(1<=pi<=n),給出了第i次翻轉操作前第i個樣品的位置。

注意如果乙個樣品已經站在了正確的位置pi上,你也應該輸出pi,表明「pi到pi的樣品」(即pi乙個樣品)應該被翻轉。

6 3 4 5 1 6 2

4 3 3 2 1

0

4 6 4 5 6 6

4 2 4 4

首先將輸入的數排個序,然後用乙個

id陣列記錄位置為i的點的大小排名。

然後就根據位置的中序遍歷來建樹。
為了保持樹的平衡,所以先把位置1定為根,把位置n定為1的右兒子。
然後用乙個

ma陣列記錄排行為i的數在平衡樹中的結點編號,這時

id陣列派上用場了。

然後每次要查詢排名為i的數,所以可以先把排名為i的數旋轉到根,然後答案就左子樹的

size+1

。然後刪掉根節點。

關於刪除,若沒有後繼可以直接刪掉,否則要先找到根節點的後繼,記得一邊找一邊下放。然後旋轉到根,再把原來的根的左子樹接到這個點的左子樹上就可以了。
然後就是區間翻轉的

down

函式:

1

void down(int

x)8 }

旋轉的時候要記得把

pre[pre[x]],pre[x],x

依次下放。

反正這是一道很鬼的題。

1 #include

2 #include3 #include4 #include5 #include6 #include7 #include

8 #include9 #include10 #include11 #include12 #include13 #include14

#define maxn 100010

15using

namespace

std;

16int pre[maxn],ch[maxn][2],id[maxn],size[maxn],tot=0,root=0

,flip[maxn],ma[maxn];

17struct

datain

[maxn];

20void updata(int

x)23

void down(int

x)30}31

void rotate(int x,int

kind)

44 inline void splay(int r,int

goal)

58else62}

63}64updata(r);

65if(goal==0) root=r;66}

67void newnode(int &x,int

fa)74

void build(int &x,int l,int r,int

fa)83

void

del_root()

92 splay(root,0

);93 ch[root][0]=ch[t][0

];94

if(ch[t][0]) pre[ch[t][0]]=root;95}

96else root=ch[root][0

];97 pre[root]=0;98

updata(root);99}

100void solve(int

n)107

}108

bool cmp(const data &a,const data &b)

112int

main()

113121 tot=0,root=0

;122 memset(in,0,sizeof(in

));123 memset(flip,0,sizeof

(flip));

124 memset(pre,0,sizeof

(pre));

125 memset(ch,0,sizeof

(ch));

126 memset(size,0,sizeof

(size));

127for(int i=1;i<=n;i++)

128 scanf("

%d",&in[i].num),in[i].id=i;

129 sort(in+1,in+n+1

,cmp);

130for(int i=1;i<=n;i++)id[in[i].id]=i;

131 ma[id[1]]=1

;132 ma[id[n]]=2

;133 newnode(root,0

);134 newnode(ch[root][1

],root);

135 build(ch[ch[root][1]][0],2,n-1,ch[root][1

]);136 updata(ch[root][1

]);137

updata(root);

138solve(n);

139 cout<<'\n'

;140

}141 }

noip2007 獎學金 (排序)

a1159.獎學金 時間限制 1.0s 記憶體限制 256.0mb 總提交次數 797ac次數 339 平均分 60.95 將本題分享到 檢視未格式化的試題 提交試題討論 試題 noip2007 普及組 問題描述 某小學最近得到了一筆贊助,打算拿出其中一部分為學習成績優秀的前5名學生發獎學金。期末,...

poj 2007 極角排序

極角排序有四種方法,我一開始就是先算出極角來,然後進行排序,可交上去卻是wa,現在還沒有搞,後面用另一種還是錯了,最後用了這種才過的!如下 include include include include include using namespace std const int maxn 55 st...

POJ 2007 叉積排序

題意 給出凸包上的點,其中乙個點是 0,0 要求從 0,0 按照逆時針輸出所有點。題解 不能有極角排序,因為多邊形可能在原點的左側。view code 1 include 2 include 3 include 4 include 5 include 6 include 7 8 define n 2...