在布拉格捷克理工大學(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
函式:
1void down(int
x)8 }
旋轉的時候要記得把
pre[pre[x]],pre[x],x
依次下放。
反正這是一道很鬼的題。
1 #include2 #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...