1. 程式人生 > >3262. 陌上花開【CDQ分治】

3262. 陌上花開【CDQ分治】

數組下標 scrip const name clu 級別 cor tor sin

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
正好借這個題的題解總結一下我對CDQ的理解
順便借這個題學了一下一直沒碰過的樹狀數組……
首先對於三維偏序$(a,b,c)$,我們可以以a為關鍵字進行sort,
這樣數組中的a就是有序的,每次分治當前區間我們只考慮左半邊對右半邊的貢獻,這樣就可以消除a的影響QAQ
再觀察一下現在要解決的問題,統計$b_{j}<=b_{i}$且$c_{j}<=c[i]$
如果我們把b當做數組下標,c當數組下標裏的值的話,可以想到什麽?逆序對!不過這裏是個順序對就是了
所以就是第一維使其sort有序,第二維分治的時候歸並排序使其有序,第三維用樹狀數組進行統計
註意要去重,否則如果A=B,那麽(A,B)(B,A)本來都是可以的,但分治的時候不去重我們只能考慮進去一種
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5
#define N (200000+1000) 6 using namespace std; 7 8 int n,k,emm,top,c[N],ans[N]; 9 10 int lowbit(int x){return x&-x;} 11 int add(int x,int delta){for (; x<=k; x+=lowbit(x)) c[x]+=delta;} 12 int sum(int x){int sum=0; for (; x; x-=lowbit(x)) sum+=c[x]; return sum;} 13 14 struct Node 15 { 16 int a,b,c,size,ans; 17 bool operator < (const Node &A) const 18 { 19 if (a==A.a && b==A.b) return c<A.c; 20 if (a==A.a) return b<A.b; 21 return a<A.a; 22 } 23 }a[N],t[N]; 24 25 void CDQ(int l,int r) 26 { 27 if (l==r) return; 28 int mid=(l+r)>>1; 29 CDQ(l,mid); CDQ(mid+1,r); 30 int i=l,j=mid+1,p=l; 31 while (i<=mid || j<=r) 32 { 33 if (j>r || i<=mid && a[i].b<=a[j].b) add(a[i].c,a[i].size),t[p++]=a[i++]; 34 else a[j].ans+=sum(a[j].c),t[p++]=a[j++]; 35 } 36 for (int i=l; i<=mid; ++i) add(a[i].c,-a[i].size); 37 for (int i=l; i<=r; ++i) a[i]=t[i]; 38 } 39 40 int main() 41 { 42 scanf("%d%d",&n,&k); emm=n; 43 for (int i=1; i<=n; ++i) 44 scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c),a[i].size=1; 45 sort(a+1,a+n+1); 46 top=1; 47 for (int i=2; i<=n; ++i) 48 { 49 if (a[i].a==a[top].a && a[i].b==a[top].b && a[i].c==a[top].c) 50 a[top].size++; 51 else a[++top]=a[i]; 52 } 53 n=top; 54 CDQ(1,n); 55 for (int i=1; i<=n; ++i) ans[a[i].ans+a[i].size-1]+=a[i].size; 56 for (int i=0; i<emm; ++i) printf("%d\n",ans[i]); 57 }

3262. 陌上花開【CDQ分治】