對家庭菜園有興趣的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,...