ICPC Southeast USA 2020 Regional Contest problem C: Bitonic Ordering(貪心)


 

題目描述

Noah suggests the following card game: You are given a deck of cards, each with a distinct positive integer value written on it. The cards are shuffled and placed in a row. Your objective is to arrange the cards in the row so that the values are monotonically increasing initially, and then monotonically decreasing for the remainder of the sequence.
The only move that is allowed is that two neighboring cards may swap positions. Cards may only swap positions if they are adjacent to each other.
Note that in the final ordered sequence, the initial increasing portion of the sequence may be empty (such that the whole sequence is in descending order). Likewise it is allowed for the decreasing
portion of the sequence to be empty. 
What is the fewest number of moves needed to get the cards arranged in the proper order?

輸入

The first line of input contains a single integer n (1 ≤ n ≤ 3 · 105 ), which is the number of cards.
Each of the next n lines contains a single integer c (1 ≤ c ≤ 109 ). These are the cards, in their initial order. They will all be distinct.

輸出

Output a single integer, which is the fewest number of moves needed to arrange the cards as specified.

樣例輸入 Copy

8
7
4
8
10
1
2
6
9

樣例輸出 Copy

7


就是讓你通過交換兩兩相鄰的數字然后達到序列是先遞增后遞減的狀態(可以只遞增/減)

這個我們首先可以確定最大值即峰值的數值是一定的,但是位置不確定
如果考慮最小值的話,不僅數值是確定的,位置也是確定的,在左右兩側
具體是移動到左邊還是移動到右邊,這里就可以采用貪心的策略,如果距離左邊近,就移動到左邊,否則移動到右邊
具體操作:

可以用map記錄每個數字的初始位置,然后看看維護一個l=1,r=n,如果移動到l的位置,就l++,r同理
如果一個數字的真實位置是pos1,初始位置是pos2
如果他移動到左邊的去
那么原區間[1,pos-1]的下標值全部加一,這里我們用樹狀數組維護就好了
CODE:
ll n,a[maxn];
map<ll,ll>mp;
priority_queue<ll,vector<ll>,greater<ll> >q;
ll ans,t[maxn];
ll lowbit(ll x) {
    return x&(-x);
}
void add(ll x,ll num) {
 
    while(x<=n) t[x]+=num,x+=lowbit(x);
}
ll qq(ll x) {
    //if(x==0) return 0;
    ll ans=0;
    while(x>0) {
        ans+=t[x];
        x-=lowbit(x);
    }
    return ans;
}
int main() {
    n=read();
    rep(i,1,n) a[i] = read(),q.push(a[i]),mp[a[i]] = i,add(i,i),add(i+1,-i);
    int l =1 ,r = n; //如果移動到左右兩側,對應的位置在哪
    while(q.size()) {
        int x = q.top();
        q.pop();
        x = mp[x];
        int pos = qq(x)  ; //真實位置
        int L = pos - l;
        int R = r-pos;
        //  cout<<pos<<endl;
        if(L<=R) {
            //移動到左邊
            //移動到l
            ans+=L;
            add(1,1);
            add(x,-1);
            l++;
 
        } else {
            //移動到右邊
            //移動到r
            ans+=R;
            add(x+1,-1);
            r--;
        }
 
    }
    out(ans);
    return  0;
}
View Code

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM