對家庭菜園有興趣的joi君每年在自家的田地中種植一種叫做ioi草的植物。joi君的田地沿東西方向被劃分為n個區域,由西到東標號為1~n。ioi草一共有n株,每個區域種植著一株。在第i個區域種植的ioi草,在春天的時候高度會生長至hi,此後便不再生長。
為了觀察春天的樣子而出行的joi君注意到了ioi草的配置與預定的不太一樣。ioi草是一種非常依靠陽光的植物,如果某個區域的ioi草的東側和西側都有比它高的ioi草存在,那麼這株ioi草就會在夏天之前枯萎。換句話說,為了不讓任何一株ioi草枯萎,需要滿足以下條件:
對於任意2<=i<=n-1,以下兩個條件至少滿足乙個:
ioi草是非常昂貴的,為了不讓ioi草枯萎,joi君需要調換ioi草的順序。ioi草非常非常的高大且纖細的植物,因此joi君每次只能交換相鄰兩株ioi草。也就是說,joi君每次需要選擇乙個整數i(1<=i<=n-1),然後交換第i株ioi草和第i+1株ioi草。隨著夏天臨近,ioi草枯萎的可能性越來越大,因此joi君想知道讓所有ioi草都不會枯萎的最少操作次數。
現在給出田地的區域數,以及每株ioi草的高度,請你求出讓所有ioi草的不會枯萎的最少操作次數。
第一行乙個正整數n,代表田地被分為了n個區域。
接下來n行,第i行(1<=i<=n)乙個整數hi,表示第i株植物在春天時的高度
輸出一行乙個整數,表示最少需要的操作次數
貪心+樹狀陣列
採用重新編號。
對於原來的陣列,重新編號為1 2 3 4 5 6
假如交換之後,這些編號交換成了1 3 4 2 6 5
變成這個最終序列操作次數就是最終序列逆序對對數。
對於這個樣例就是3
(證明:考慮反過來,乙個序列變成公升序的,就是逆序對數量,所以,從公升序變成這個序列,也是逆序對對數)
現在就要考慮怎麼構造。
使得最終的序列合法,並且逆序對數最少。
類似於各種排序問題
按h 從大到小sort
之前放好的h們成了乙個塊。
後面的h小的,為了保證合法,只能往之前的塊的左邊或者右邊放。
貪心放置,每次選擇已經塊的左邊或者右邊,使得新的逆序對最小。
(證明:放完之後,和之前塊形成乙個新的塊。塊內的放置方法不會對後面的逆序對產生帶來影響。
所以自然已經放置的塊裡逆序對最少是成立的。)
至於這個決策,用兩個樹狀陣列處理,乙個查詢比i小的,乙個查詢比i大的。
相同的權值,先一起查詢,然後一起放置。因為相同權值之間不會因為下標逆序對產生代價。
**:
#includeusingnamespace
std;
typedef
long
long
ll;const
int n=3e5+5
;ll ans;
intn;
intst[n];
struct
tr
int query(int
x)}max,min;
struct
node
}a[n];
intsta[n],top;
intmain()
sort(a+1,a+n+1
);
//cout<<" bug "i--;
for(int j=1;j<=top;j++)
//cout<<" hha "(top)
}printf(
"%lld
",ans);
return0;
}
總結:突破口:重新編號,轉化為最終序列的編號序列的逆序對數。還有對h排序,為了不造成影響,並且放置方便(只能往左右放)。
然後就是貪心關鍵點:先放置大的形成了一塊,塊內的放置方法不會對後面的逆序對產生帶來影響。
可以注意到,對於排序的問題,通常可以把編號什麼的條件排個序決策,
好處是,我們可以自然而然地獲得了一些性質,而避免了狀壓。
JOI 有趣的有趣的家庭菜園Fgarden
職業經營家庭菜園的joi君每年在自家的田地中種植一種叫做ioi草的植物。ioi草的種子在冬天被播下,春天會發芽並生長至乙個固定的高度。到了秋天,一些ioi草會結出美麗的果實,並被收穫,其他的ioi草則會在冬天枯萎。joi君的田地沿東西方向被劃分為n個區域,從西側開始的第i個區域中種植著ioi草i。在...
BZOJ4240 有趣的家庭菜園
給出乙個長度為n的序列,可以將相鄰的數交換位置,要求通過最少交換次數使得這個序列呈左邊段不遞減,右邊段不遞增 樹狀陣列 貪心 將每個數一開始的下標為原本的位置,最後得到的序列的逆序對數就是操作的次數 首先得到的序列肯定是最大的在中間,第二大的在旁邊。那麼就貪心放值,放的時候找左右兩邊能產生逆序對最少...
BZOJ 4240 有趣的家庭菜園
第一道樹狀陣列 用到了貪心的想法 交換的代價就是交換完之後的逆序對數 將所有ioi草從高到低放入 貪心判斷是放在左邊還是放在右邊 會爆int 也要考慮有兩棵ioi草高度相同 include include include include using namespace std const int m...