BZOJ4240 有趣的家庭菜園 樹狀陣列 貪心

2022-05-20 16:07:23 字數 1508 閱讀 8339

對家庭菜園有興趣的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株植物在春天時的高度

輸出一行乙個整數,表示最少需要的操作次數62

8453

63最終的高度序列為2 4 5 8 6 3,共需要操作三次。

3<=n<=3*10^5

1<=hi<=10^9

題解:乙個經常用到的結論:我們給原陣列標上下表1...n,移動若干次後我們會得到乙個新的下標序列,需要的搬運次數就是這個新序列的逆序對數。

所以我們思考怎樣讓新序列的逆序對數更少就行了。題中要求最終序列滿足h值先遞增再遞減,所以最大的一定放到中間,次大的可以放在最大的兩邊,再次的放在前兩大的兩邊。。。所以,當放入第k大的時候,我們貪心選擇可以形成較少的逆序對的那邊放,並且這樣做不會影響到後面的節點。

還有如果多個草高度相同要特判一下。

#include #include #include #include using namespace std;

const int maxn=300010;

typedef long long ll;

ll ans;

int n,l,r;

int s[maxn],v[maxn],p[maxn];

void updata(int x,int val)

int query(int x)

bool cmp(int a,int b)

int rd()

while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();

return ret*f;

}int main()

for(;i<=j;i++) updata(p[i],1);

} printf("%lld",ans);

return 0;

}

BZOJ4240 有趣的家庭菜園

給出乙個長度為n的序列,可以將相鄰的數交換位置,要求通過最少交換次數使得這個序列呈左邊段不遞減,右邊段不遞增 樹狀陣列 貪心 將每個數一開始的下標為原本的位置,最後得到的序列的逆序對數就是操作的次數 首先得到的序列肯定是最大的在中間,第二大的在旁邊。那麼就貪心放值,放的時候找左右兩邊能產生逆序對最少...

BZOJ 4240 有趣的家庭菜園

第一道樹狀陣列 用到了貪心的想法 交換的代價就是交換完之後的逆序對數 將所有ioi草從高到低放入 貪心判斷是放在左邊還是放在右邊 會爆int 也要考慮有兩棵ioi草高度相同 include include include include using namespace std const int m...

bzoj 4240 有趣的家庭菜園 樹狀陣列

隨手寫了一發rank1什麼鬼。因為4239有點繁瑣,就先跳過去了。然後看完這道題目就懵逼了。o o 但是仔細想想會發現對於一棵草,它的移動是不會影響到比它更高的草的,因此我們可以從小到大移動草,並且貪心地移動到較小的一邊,換句話說令f i,j,k 表示i j中比k大的數的個數,那麼對於某一棵草 x,...