題意: 給出長度為n的序列,每次只能交換相鄰的兩個元素,問至少要交換幾次才使得該序列為遞增序列?
題解:其實就是求逆序對的數量。可以用樹狀陣列來求。雖然數的大小為 999,999,999,但是數的規模只有500,000,所以可以對資料進行離散化,之後就可以用樹狀陣列來求了。
**:#include #include #include #include using namespace std;
const int max=500000+5;
typedef long long ll;
int bit[max];
int a[max];
int tmp[max];
int n;
int sum(int x)
return sum;
}void add(int x,int value)
}int main()
cout<
題意:給定乙個序列,對該序列的n種排列(排列如下)的每種排列的逆序數求最大值:
a1, a2, ..., an-1, an
a2, a3, ..., an, a1
a3, a4, ..., an, a1, a2
...
an, a1, a2, ..., an-1
題解:我們可以分為n步,每次都將第乙個元素移動到最後乙個,這樣原來的逆序對變為順序對,原來的順序對變為逆序對,所以逆序對減少的數量為(比他小的數的個數)減去(比他大的數的個數),即cnt-(n-1-cnt)=2*cnt-n+1,cnt為比當前數小的數,cnt可以用樹狀陣列求出,但是因為每次操作的都是第乙個數,並且數只有1-n,所以cnt就等於a[i]-1。cnt-(n-1-cnt)=2*cnt-n+1=2*a[i]-n-1。進行n步求出逆序對減少的數量的最大值用總的逆序對數減去這個值即可。
**:
#include #include #include #include #include using namespace std;
const int max=5000+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
int a[max];
int rs[max];
int bit[max];
int n;
int sum(int x)
return s;
}void add(int x,int v)
}int main()
{ int n;
while(scanf("%d",&n)!=eof)
{memset(bit,0,sizeof(bit));
n=n;
int tol=0;
for(int i=0;i
樹狀陣列求逆序對(逆序數)
逆序數 也叫逆序對 在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序。乙個排列中逆序的總數就稱為這個排列的逆序數。無重複的數 include include include include include include using namespace...
樹狀陣列 題目詳解
樹狀陣列直接搜狗百科就行 不行再去b站 巨佬寫的 includeusing namespace std const int maxn 1e5 int f maxn int n int lowbit int x void update int i,int x int query int n retur...
樹狀陣列求逆序數
逆序數就是數中各位在它前面有多少個數比它大,求出這些元素個數之和。今天看了個樹狀陣列,可以很好的解決這個問題,普通方法需要o n 2 複雜度,用樹狀陣列只需要o nlongn 樹狀陣列實際上還是乙個陣列,只不過它的每個元素儲存了跟原來陣列的一些元素相關的結合值。若a為原陣列,定義陣列c為樹狀陣列。c...