3262: 陌上花开

3262: 陌上花开

链接

 

分析

  三维偏序问题。CDQ分治+树状数组。

  首先没注意如何输出,就只直接把f[i]输出了,调啊调......然后没注意是小于等于又调啊调......最后没有特判相同的,看了题解才知道......

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4  
 5 inline int read() {
 6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 8 }
 9  
10 const int N = 100100;
11 int ans[N],d[N],n,m;
12 struct Node{
13     int x,y,z,cnt,ans;
14     bool operator < (const Node &a) const {
15         if (x == a.x && y == a.y) return z < a.z;
16         if (x == a.x) return y < a.y;
17         return x < a.x; 
18     }
19 }A[N],B[N];
20 struct BIT{
21     int sum[N<<1];
22     void update(int p,int v) {
23         for (; p<=m; p+=p&(-p)) sum[p] += v;
24     }
25     int query(int p) {
26         int ans = 0;
27         for (; p; p-=p&(-p)) ans += sum[p];
28         return ans;
29     }
30     int clear(int p) {
31         for (; p<=m&&sum[p]; p+=p&(-p)) sum[p] = 0;
32     }
33 }bit;
34  
35 void CDQ(int L,int R) {
36     if (L == R) {A[L].ans += A[L].cnt - 1;return ;}
37     int M = (L + R) >> 1;
38     CDQ(L,M);
39     CDQ(M+1,R);
40     int i = L,j = M + 1,k = L;
41     while (i <= M && j <= R) {
42         if (A[i].y <= A[j].y ) { // 对y进行排序,y相同时,z最初已经排好了。 
43             bit.update(A[i].z,A[i].cnt);
44             B[k++] = A[i++];
45         }
46         else {
47             A[j].ans += bit.query(A[j].z);
48             B[k++] = A[j++];
49         }
50     }
51     while (i <= M) B[k++] = A[i++];
52     while (j <= R) {
53         A[j].ans += bit.query(A[j].z);
54         B[k++] = A[j++];
55     }
56     for (i=L; i<=R; ++i) {
57         bit.clear(A[i].z);
58         A[i] = B[i];
59     }
60 }
61 int main() {
62     n = read(),m = read(); 
63     for (int i=1; i<=n; ++i) {
64         A[i].x = read(),A[i].y = read(),A[i].z = read(),A[i].cnt = 1;
65     }
66     sort(A+1,A+n+1);
67     int tot = 1;
68     for (int i=2; i<=n; ++i) { // 去除相同的元素。 
69         if (A[i].x == A[tot].x && A[i].y == A[tot].y && A[i].z == A[tot].z) A[tot].cnt ++;
70         else A[++tot] = A[i];
71     }
72      
73     CDQ(1,tot);
74     for (int i=1; i<=tot; ++i) ans[A[i].ans] += A[i].cnt;
75     for (int i=0; i<n; ++i) printf("%d\n",ans[i]);
76     return 0;
77 }

 

转载于:https://www.cnblogs.com/mjtcn/p/9231069.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值