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
排序消去$a$的影响,归并排序的过程消除$b$的影响,然后利用树状数组统计答案
代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #define M 200010
6 using namespace std;
7 int n,k;
8 int val[M],ans[M];
9 struct CDQ{int a,b,c,val,ans;}p[M],tmp[M];
10 bool cmp(CDQ a,CDQ b) {
11 return a.a==b.a?(a.b==b.b?a.c<b.c:a.b<b.b):a.a<b.a;
12 }
13 void change(int loc,int v) {
14 for(int i=loc;i<=k;i+=i&(-i)) val[i]+=v;
15 }
16 int query(int loc) {
17 int ans=0;
18 for(int i=loc;i;i-=i&(-i)) ans+=val[i];
19 return ans;
20 }
21 void solve(int l,int r) {
22 if(l==r) return;int mid=(l+r)/2;
23 solve(l,mid),solve(mid+1,r);
24 int t1=l,t2=mid+1,now=l;
25 while(t1<=mid||t2<=r) {
26 if((t1<=mid&&p[t1].b<=p[t2].b)||t2>r) {
27 change(p[t1].c,p[t1].val);
28 tmp[now++]=p[t1++];
29 }
30 else {
31 p[t2].ans+=query(p[t2].c);
32 tmp[now++]=p[t2++];
33 }
34 }
35 for(int i=l;i<=mid;i++) change(p[i].c,-p[i].val);
36 for(int i=l;i<=r;i++) p[i]=tmp[i];
37 }
38 int main() {
39 scanf("%d%d",&n,&k);
40 for(int i=1;i<=n;i++) {
41 scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].c);
42 p[i].val=1;
43 }
44 sort(p+1,p+1+n,cmp);int now=1;
45 for(int i=2;i<=n;i++) {
46 if(p[i].a==p[now].a&&p[i].b==p[now].b&&p[i].c==p[now].c) p[now].val++;
47 else p[++now]=p[i];
48 }
49 solve(1,now);
50 for(int i=1;i<=now;i++) ans[p[i].ans+p[i].val-1]+=p[i].val;
51 for(int i=0;i<n;i++) printf("%d\n",ans[i]);
52 return 0;
53 }