今天首先把樹狀陣列中求逆序數的演算法看了一下,然後看了一下線段樹的課件。
逆序數的基本框架如下:
#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 記錄以該...