1. 程式人生 > >[BZOJ3262]陌上花開

[BZOJ3262]陌上花開

algorithm scu ace ons logs bzoj med pre span

3262: 陌上花開

Time Limit: 20 Sec Memory Limit: 256 MB Submit: 2497 Solved: 1115 [Submit][Status][Discuss]

Description

有n朵花,每朵花有三個屬性:花形(s)、顏色(c)、氣味(m),又三個整數表示。現要對每朵花評級,一朵花的級別是它擁有的美麗能超過的花的數量。定義一朵花A比另一朵花B要美麗,當且僅當Sa>=Sb,Ca>=Cb,Ma>=Mb。顯然,兩朵花可能有同樣的屬性。需要統計出評出每個等級的花的數量。

Input

第一行為N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分別表示花的數量和最大屬性值。
以下N行,每行三個整數si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的屬性

Output

包含N行,分別表示評級為0...N-1的每級花的數量。

Sample Input

10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1

Sample Output

3
1
3
0
1
0
1
0
0
1

HINT

1 <= N <= 100,000, 1 <= K <= 200,000

CDQ分治 先把相同的花合並到一起,因為如果不合並的話在前面的花統計不到在後面的花 先保證$a$單調不降 然後在分治過程中一邊以$b$為關鍵字歸並,一邊把$c$插入到權值樹狀數組裏 註意在$b$相同的時候先處理左區間的 還有樹狀數組要每次清空,但清空方式一定要是怎麽插怎麽刪 我第一次寫竟然寫出了$O(nk)$的復雜度來清空樹狀數組。。。真是石樂誌 時間復雜度滿足關系$T(n)=2T(\frac{n}{2})+O(nlogn)$且$T(1)=O(1)$ 根據主定理得到$T(n)=O(nlog^2n)$
#include <cstdio>
#include 
<algorithm> using namespace std; char buf[10000000], *ptr = buf - 1; inline int readint(){ int n = 0; char ch = *++ptr; while(ch < 0 || ch > 9) ch = *++ptr; while(ch <= 9 && ch >= 0){ n = (n << 1) + (n << 3) + ch - 0; ch = *++ptr; }
return n; } const int maxn = 100000 + 10, maxk = 200000 + 10; int n, k; int arr[maxk] = {0}; inline void Update(int w, int s){ for(; w <= k; w += w & -w) arr[w] += s; } inline int Query(int w){ int s = 0; for(; w; w -= w & -w) s += arr[w]; return s; } struct Node{ int a, b, c, id, s; Node(){} Node(int _a, int _b, int _c, int _id = 0, int _s = 1): a(_a), b(_b), c(_c), id(_id), s(_s){} }tp[maxn], no[maxn]; class cmp{ public: bool operator () (const Node &x, const Node &y){ return x.a == y.a ? x.b == y.b ? x.c < y.c : x.b < y.b : x.a < y.a; } }; int rank[maxn] = {0}, cnt[maxn] = {0}; void CDQ(int l, int r){ if(l == r) return; int mid = l + r >> 1, ll = l, rr = mid + 1, tcnt = 0; CDQ(l, mid); CDQ(mid + 1, r); while(ll <= mid && rr <= r){ if(no[ll].b <= no[rr].b){ Update(no[ll].c, no[ll].s); tp[++tcnt] = no[ll++]; } else{ rank[no[rr].id] += Query(no[rr].c); tp[++tcnt] = no[rr++]; } } while(ll <= mid){ Update(no[ll].c, no[ll].s); tp[++tcnt] = no[ll++]; } while(rr <= r){ rank[no[rr].id] += Query(no[rr].c); tp[++tcnt] = no[rr++]; } for(int i = l; i <= mid; i++) Update(no[i].c, -no[i].s); for(int i = 1; i <= tcnt; i++) no[l + i - 1] = tp[i]; } int main(){ fread(buf, sizeof(char), sizeof(buf), stdin); int N = readint(); n = 0; k = readint(); tp[0] = Node(0, 0, 0, 0, 0); for(int a, b, c, i = 1; i <= N; i++){ a = readint(); b = readint(); c = readint(); tp[i] = Node(a, b, c); } sort(tp + 1, tp + N + 1, cmp()); for(int i = 1; i <= N; i++){ if(tp[i].a == no[n].a && tp[i].b == no[n].b && tp[i].c == no[n].c) no[n].s++; else no[++n] = Node(tp[i].a, tp[i].b, tp[i].c, n); } CDQ(1, n); for(int i = 1; i <= n; i++) cnt[rank[no[i].id] + no[i].s - 1] += no[i].s; for(int i = 0; i < N; i++) printf("%d\n", cnt[i]); return 0; }

[BZOJ3262]陌上花開