【BZOJ4240】有趣的家庭菜園 樹狀數組+貪心
阿新 • • 發佈:2017-07-06
main etc ron 可能性 tchar -s return 可能 include
2. 對於任意i+1<=j<=N,hk<=hi
IOI草是非常昂貴的,為了不讓IOI草枯萎,JOI君需要調換IOI草的順序。IOI草非常非常的高大且纖細的植物,因此JOI君每次只能交換相鄰兩株IOI草。也就是說,JOI君每次需要選擇一個整數i(1<=i<=N-1),然後交換第i株IOI草和第i+1株IOI草。隨著夏天臨近,IOI草枯萎的可能性越來越大,因此JOI君想知道讓所有IOI草都不會枯萎的最少操作次數。
現在給出田地的區域數,以及每株IOI草的高度,請你求出讓所有IOI草的不會枯萎的最少操作次數。
輸出一行一個整數,表示最少需要的操作次數
2
8
4
5
3
6
【BZOJ4240】有趣的家庭菜園
Description
對家庭菜園有興趣的JOI君每年在自家的田地中種植一種叫做IOI草的植物。JOI君的田地沿東西方向被劃分為N個區域,由西到東標號為1~N。IOI草一共有N株,每個區域種植著一株。在第i個區域種植的IOI草,在春天的時候高度會生長至hi,此後便不再生長。 為了觀察春天的樣子而出行的JOI君註意到了IOI草的配置與預定的不太一樣。IOI草是一種非常依靠陽光的植物,如果某個區域的IOI草的東側和西側都有比它高的IOI草存在,那麽這株IOI草就會在夏天之前枯萎。換句話說,為了不讓任何一株IOI草枯萎,需要滿足以下條件: 對於任意2<=i<=N-1,以下兩個條件至少滿足一個: 1. 對於任意1<=j<=i-1,hj<=hiInput
第一行一個正整數N,代表田地被分為了N個區域。 接下來N行,第i行(1<=i<=N)一個整數hi,表示第i株植物在春天時的高度Output
Sample Input
62
8
4
5
3
6
Sample Output
3HINT
最終的高度序列為2 4 5 8 6 3,共需要操作三次。 3<=N<=3*10^5 1<=hi<=10^9題解:一個經常用到的結論:我們給原數組標上下表1...n,移動若幹次後我們會得到一個新的下標序列,需要的搬運次數就是這個新序列的逆序對數。
所以我們思考怎樣讓新序列的逆序對數更少就行了。題中要求最終序列滿足h值先遞增再遞減,所以最大的一定放到中間,次大的可以放在最大的兩邊,再次的放在前兩大的兩邊。。。所以,當放入第k大的時候,我們貪心選擇可以形成較少的逆序對的那邊放,並且這樣做不會影響到後面的節點。
還有如果多個草高度相同要特判一下。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> 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) { for(int i=x;i<=n;i+=i&-i) s[i]+=val; } int query(int x) { int i,ret=0; for(i=x;i;i-=i&-i) ret+=s[i]; return ret; } bool cmp(int a,int b) { return v[a]>v[b]; } int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } int main() { scanf("%d",&n); int i,j,a; for(i=1;i<=n;i++) v[i]=rd(),p[i]=i; sort(p+1,p+n+1,cmp); for(i=1;i<=n;) { for(j=i;j<=n;j++) { a=query(p[j]),ans+=min(a,i-1-a); if(v[p[j+1]]!=v[p[j]]) break; } for(;i<=j;i++) updata(p[i],1); } printf("%lld",ans); return 0; }
【BZOJ4240】有趣的家庭菜園 樹狀數組+貪心