題目大意
n個數排成一排(不知道大小,只是佔了乙個位置),從a[1]到a[n]進行遍歷,對於每個a[i],給出從a[1]到a[i-1]中小於a[i]數的個數。要求出 a[1]到a[n]中這n個數的相對順序。
題目分析
則 a[i] 在所有n個數中的序號(按照從小到大排序)為 k = less[i] + t + 1
但是,t並不好直接求出,則觀察k的性質。對於a[i]在所有n個數中的位置k,1---k-1中包括 less[i]個在 a[1] -- a[i-1]中的元素,同時包括t個在a[i+1]---a[n]中的元素,在a[i+1]---a[n]中的元素已經確定了他們在整個n個數中的位置(我們是從後往前進行計算的),則 1----k-1中就可以確定那t個元素的位置。
為了確定k的位置,則設定乙個陣列b[1]--b[n],初始全部為0,從n到1統計,若a[i]的位置確定下來為p,則 b[p] = 1.則對於任意的k,b[1]---b[k]中1的個數表示 1----k中被占用的位置,0 的位置表示未被占用的位置。
對於 a[i],找到某個k,使得其b[1]--b[k-1]中0的個數正好為 less[i]個,則k的位置就是 a[i]在整個n個數中的按照大小排序的位置
實現(c++)
1. 線段樹
#define _crt_secure_no_warnings
#include#include#define max_cow_num 80010
#define max_node_num 4*max_cow_num
int gless[max_cow_num];
int gpos[max_cow_num];
struct node
};node gnodes[max_node_num];
void buildtree(int beg, int end, int index)
int left = 2 * index + 1;
int right = 2 * index + 2;
int mid = (beg + end) >> 1;
buildtree(beg, mid, left);
buildtree(mid + 1, end, right);
gnodes[index].sum_zero = gnodes[left].sum_zero + gnodes[right].sum_zero;
}//對於每個數 a[i], 給出了從 a[1] -- a[i-1]中小於a[i]的個數 less[i].
//從n到1逆序檢視, less[n] 表示前n-1個數中小於a[n]的個數,則可以確定a[n]的位置為 less[n] + 1
//類似的對於 i,為了確定a[i]在所有n個數中的序號,將這個任務分為兩部分:
//(1)在 a[1] -- a[i-1]中有多少個數小於a[i], 題目給出了為 less[i]
//(2)在a[i+1]---a[n]中有多少個數小於 a[i], 設為t
//則 a[i] 在所有n個數中的序號(按照從小到大排序)為 k = less[i] + t + 1
//t 並不好直接求出,則觀察k的性質。對於a[i]在所有n個數中的位置k,1---k-1中包括 less[i]個在 a[1] -- a[i-1]中的元素,
//同時包括 t個在a[i+1]---a[n]中的元素,在a[i+1]---a[n]中的元素已經確定了他們在整個n個數中的位置(我們是從後往前進行計算的),
//則 1----k-1中就可以確定那t個元素的位置。
//為了確定k的位置,則設定乙個陣列 b[1]--b[n],初始全部為0,從n到1統計,若a[i]的位置確定下來為p,則 b[p] = 1.
//則對於任意的k,b[1]---b[k]中1的個數表示 1----k中被占用的位置,0 的位置表示未被占用的位置。
//對於 a[i],找到某個k,使得其b[1]--b[k-1]中0的個數正好為 less[i]個,則k的位置就是 a[i]在整個n個數中的按照大小排序的位置
//利用線段樹,找到 b[1]---b[pos]中 0的個數為k個的pos的位置
void findkth(int k, int index, int& pos)
if (gnodes[index].beg == gnodes[index].end)
int left = 2 * index + 1, right = 2 * index + 2;
gnodes[index].sum_zero--;
if (gnodes[left].sum_zero >= k)
else
}int main()
int pos = 0;
gless[1] = 0;
for (int i = n; i >= 1; i--)
for (int i = 1; i <= n; i++)
return 0;
}
2. 樹狀陣列
#define _crt_secure_no_warnings
#include#include#include#define max_cow_num 80010
int glowbit[max_cow_num];
int gc[max_cow_num];
int gless[max_cow_num];
int gpos[max_cow_num];
bool gused[max_cow_num];
void initlowbit(int n)
}void initsequence(int n)
}//樹狀陣列的更新
void update(int p, int n, int add)
}//樹狀陣列的查詢
int query(int p)
return result;
}//二分法,查詢滿足要求的 位置
int search(int k, int n)
return mid + 1;
} else if (sum_zero < k)
else
} return 1;
}int main()
for (int i = n; i >= 1; i--)
for (int i = 1; i <= n; i++)
return 0;
}
poj 2182 樹狀陣列
這題對於o n 2 的演算法有很多,我這隨便貼乙個爛的,跑了375ms。include include using namespace std int mat 8008 int main for i 0 i printf d n mat i return0 view code 還是來看樹狀陣列的解法...
poj2182 樹狀陣列 二分)
題意 給乙個數n,然後n 1行,每行乙個數q,第i個數qi代表第i 1頭牛前面有qi頭牛編號比它小,求所有牛的編號。因為只有最後一頭牛編號是確定的,所有從後往前,每次用二分找到數字,並用樹狀陣列確定和儲存。include include include includeusing namespace ...
poj 2182 單點修改
題意 有n頭牛,標號從1到n,現在牛排成乙個佇列,知道每個牛的前面比自己標號小的牛的數量,輸出每個牛的標號。題解 給出的序列的最後乙個數字是可以推出的,然後把這個數字拿走,又能知道前面有幾個數字,和之前做過的有幾個空位乙個道理,維護線段樹區間解決。include include include us...