覺得開始需要著手練下線段樹了,所以從單點更新開始著手。
題目大意:給定乙個長度為n的序列,然後每次將序列當中的第乙個數放在序列末尾,這樣我們一共會得到n個序列。每個序列都會有個逆序數,取這n個數當中的最小的作為結果輸出。
最最暴力的方法是把這n種情況排列出來,然後每種情況都算一下逆序數,然後取最小。
由於暴力演算法計算一組情況逆序數的時間複雜度是o(n^2)的,n為小於等於5000的數,所以我們可以考慮下能否用一組逆序數推出其他所有情況逆序數的結果呢?由於本題的特殊性,是可以做到的,首先n個數中分別是[0, n - 1]當中的數字而且無重複數字出現,那麼我們假設已知的某一串行的逆序數為sum,那麼它的下乙個序列式將a0放到隊尾,那麼序列中的其他數字必然都在它的前面(包括a0個比它小的數和n - a0 - 1個比它大的數),也就是說逆序數sum會減少a0個,增加n - a0 - 1個。
即sum = sum - (a0) + (n - a0 - 1);
暴力o(n^2)做法**:(218ms)
#include #include #include #include using namespace std;
int a[5010];
int n;
int main()
}for(int i = 0; i < n; i++)
printf("%d\n", ans);
}return 0;
}
線段樹做法的核心部分和暴力法相同,也是只構建一棵空樹,按照輸入的順序更新和查詢加和。
線段樹:(78ms) 剛開始寫,線段樹的格式還有待學習和習慣,雖然格式被吐槽了。。不過還是覺得封裝起來舒服
#include #include #include #include using namespace std;
#define max 5010
#define ll(x) (x << 1)
#define rr(x) (x << 1 | 1)
#define mid(x, y) (x + ((y - x) >> 1))
int n;
int a[max];
class tnode
void init()
};class segment_tree
}void update(int pos, int t)
}int query(int st, int ed, int t)
}}seg;
int main()
int ans = 1e9;
for(int i = 1; i <= n; i++)
printf("%d\n", ans);
}return 0;
}
hdu 1394 求逆序數
首先建立空樹,將 a i 逐個插入 計算乙個序列n排列的最小逆序數 首先用線段樹算出出事序列的逆序數,然後找規律推出排列的最小逆序數。include include include include include include include include include include inc...
HDU1394 求逆序數
hdu1394minimum inversion number 逆序數 a i 後面比它小的數的個數即為a i 的逆序數,題目要求的是序列的逆序數,求和即可 題意 乙個由0.n 1組成的序列,每次可以把隊首的元素移到隊尾,求形成的n個序列中最小逆序數 思路 乙個序列的逆序數可以用線段樹,或者暴力法求...
hdu 1394 線段樹求逆序數
線段樹求逆序數 求小逆序數 神奇 題意 給定乙個序列,對該序列的n種排列 排列如下 的每種排列 0 n 1 的逆序數求最小值 a1,a2,an 1,an a2,a3,an,a1 a3,a4,an,a1,a2 an,a1,a2,an 1 思路 先求出初始序列的逆序數,可以歸併,這裡用的是線段數求。設當...