poj2481-樹狀數組

來源:互聯網
上載者:User

這裡就是求區間覆蓋問題,如果你的區間完全覆蓋它的,那麼你就比他強壯。求出比自己強壯的牛數。

 

樹狀數組:

樹狀數組是一個查詢和修改複雜度都為log(n)的資料結構,假設數組a[1..n],

 

用lowbit函數維護了一個樹的結構

那麼查詢a[1]+...+a[n]的時間是log層級的,而且是一個線上的資料結構,

  支援隨時修改某個元素的值,複雜度也為log層級。

  來觀察這個圖:

  令這棵樹的結點編號為C1,C2...Cn。令每個結點的值為這棵樹的值的總和,那麼容易發現:

  C1 = A1

  C2 = A1 + A2

  C3 = A3

  C4 = A1 + A2 + A3 + A4

  C5 = A5

  C6 = A5 + A6

  C7 = A7

  C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8

  ...

  C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16

  這裡有一個有趣的性質:

  設節點編號為x,那麼這個節點管轄的區間為2^k(其中k為x二進位末尾0的個數)個元素。因為這個區間最後一個元素必然為Ax,

  所以很明顯:Cn = A(n – 2^k + 1) + ... + An

  算這個2^k有一個快捷的辦法,定義一個函數如下即可:

  int lowbit(int x){

  return x&(x^(x–1));

  }

  當想要查詢一個SUM(n)(求a[n]的和),可以依據如下演算法即可:

  step1: 令sum = 0,轉第二步;

  step2: 假如n <= 0,演算法結束,返回sum值,否則sum = sum + Cn,轉第三步;

  step3: 令n = n – lowbit(n),轉第二步。

  可以看出,這個演算法就是將這一個個區間的和全部加起來,為什麼是效率是log(n)的呢?以下給出證明:

  n = n – lowbit(n)這一步實際上等價於將n的二進位的最後一個1減去。而n的二進位裡最多有log(n)個1,所以查詢效率是log(n)的。

  那麼修改呢,修改一個節點,必須修改其所有祖先,最壞情況下為修改第一個元素,最多有log(n)的祖先。

  所以修改演算法如下(給某個結點i加上x):

  step1: 當i > n時,演算法結束,否則轉第二步;

  step2: Ci = Ci + x, i = i + lowbit(i)轉第一步。

  i = i +lowbit(i)這個過程實際上也只是一個把末尾1補為0的過程。

  對於數組求和來說樹狀數組簡直太快了!

代碼:

注意這裡下排序,按照s,e中的e從大到小,如果e相等-s從小到大排序。這樣,比自己強壯的只能是前面的,而數組數組只需要記錄起始點就可以了。注意區間相同的話就是實力相當不能計算在內。

#include <stdio.h>#include <stdlib.h>#include <string.h>#define nMax 100010#define Max(a,b) (a>b?a:b)#define Min(a,b) (a<b?a:b)struct COW{int s,e,id;}cow[nMax];int ans[nMax];int cnt[nMax];int maxN = -1;//比較函數,按照e從大到小,s從小到大int cmp(const void * a, const void * b){struct COW *c = (struct COW *)a;struct COW *d = (struct COW *)b;if (c->e == d->e){return c->s - d->s;}elsereturn d->e - c->e;}//樹狀數組的三個函數,一個是求x的最後一個1的位置,在某一位置增加一個數,求出num以前的所有數的和這三個函數int lowbit(int x){return x&(x^(x - 1));}void add(int pos){while (pos <= maxN + 1){ans[pos] ++;pos += lowbit(pos);}}int sum(int num){int sum = 0;while (num > 0){sum += ans[num];num -= lowbit(num);}return sum;}int main(){int n;while (scanf("%d", &n) && n){maxN = -1;for (int i = 1; i <= n; ++ i){scanf("%d %d", &cow[i].s, &cow[i].e);cow[i].id = i;maxN = Max(maxN, cow[i].e);}memset(ans, 0, sizeof(ans));qsort(cow + 1, n, sizeof(cow[0]), cmp);for (int i = 1; i <= n; ++ i){if (cow[i].s == cow[i - 1].s && cow[i].e == cow[i - 1].e)//相等的話,不計算在內{cnt[cow[i].id] = cnt[cow[i - 1].id];}else//否則可以求出覆蓋本區間的所有牛的個數,由於排序,只能在前面cnt[cow[i].id] = sum(cow[i].s + 1);add(cow[i].s + 1);//將本區間的起始點加入到樹狀數組中}for (int i = 1; i < n; ++ i){printf("%d ", cnt[i]);}printf("%d\n", cnt[n]);}return 0;}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.