訓練日記 16

2021-08-07 08:08:57 字數 1764 閱讀 6030

今天首先把樹狀陣列中求逆序數的演算法看了一下,然後看了一下線段樹的課件。

逆序數的基本框架如下:

#include

#include

#include

#include

#include 

using namespace std;

int b[500005], c[500005];

int n;

struct node

int num, id;

}a[500005];

bool cmp(node a, node b)

return a.num < b.num;

void update(int i, int x)

while(i <= n)

c[i] += x;

i += i&(-i);

int sum(int i)

int sum = 0;

while(i > 0)

sum += c[i];

i -= i&(-i);

return sum;

int main()

int i;

long long ans;

while(scanf("%d", &n), n)

memset(b, 0, sizeof(b));

memset(c, 0, sizeof(c));

for(i = 1; i <= n; i++)

scanf("%d", &a[i].num); //輸入數值

num

a[i].id = i;            //記錄序號id

///開始離散化

sort(a+1, a+n+1, cmp);  //先排序

/*因為

a[1].num

是最小的,

id是它的位置,所以

b[a[1].id]=1

最小,

最小的數變成1,第二小的變成

2,如此類推從而達到離散化*/

b[a[1].id] = 1;

for(i = 2; i <= n; i++)

if(a[i].num != a[i-1].num)

b[a[i].id] = i;

else b[a[i].id] = b[a[i-1].id];

///離散化完畢

ans = 0;

for(i = 1; i <= n; i++)

update(b[i], 1);

//這裡很巧妙,每一次更新後,判斷此數比左邊的數小的數有多少

ans += (sum(n)-sum(b[i]));

//從而求到:右邊的數比左邊的數大的個數的總和

printf("%i64d\n", ans);

//這裡必須注意一下,資料比較大的話不用64位很容易出錯,所以最好還是用64位輸出

看到訓練三一直關著,最近一直在看課件跟例題,我一直納悶這麼多天了訓練三為什麼一直關著。。。今晚上問了一下別人才知道還有乙個開著的訓練三。。。 很鬱悶,很絕望。 然後今晚上的時間就先刷了兩道a的最多的兩道題,一道是二維樹狀陣列問題,另一道是剛看的求逆序數的問題。

從明天開始要正式開始刷題了!

繼續加油!

訓練日記 20161024

初賽好像不會掛了,好開心!版權原因,不上傳題目。題意 求1 n n 1000 的排列中逆序對恰好為 k 個的排列數目。多測。題解 f i j 表示前 i 個數,逆序對個數恰好為 j的排列個數,易得轉移方程f i j i 1k 0f i 1 j k 用字首和優化可使複雜度降為o n2 題意 對於乙個長...

訓練日記 20170324

長久不更新部落格了。期間經歷了恰好被ag線踩的wc,經歷了漫長痛苦的小高考準備。現在終於可以重整旗鼓,向省選進發!幾個月來,唯一不變的是我仍然是個超級蒟蒻 版權原因,不上傳題目。題意 最小樹形圖 去年就接觸 聽說 過的演算法,一直沒有真正寫過。因為各種奇怪的細節錯誤,調了好幾個小時 比如找環時沒有判...

訓練日記 20170328

今天的題目似乎很水 好多人都提前ak離場了,於是提前一小時收題。但是我還是各種不會。思維江化?話說,聽到一句很有趣的話 山不在高,有林則徐 水不在深,有江 題意 給定一棵有n n 105 個節點的有根樹,編號互不重複。詢問有多少棵子樹內節點編號構成乙個連續區間。題解 水題,對於每個節點 i 記錄以該...