【模板】三维偏序

 

CDQ分治

首先按a排序,分成两段后再分别对两段按b排序,这样就保证了w[x2].a>=w[x1].a,消去一维

按b排序后找到w[x2].b>=w[x1].b的同时满足w[x2].c>=w[x1].c的值

按b排序后有单调性,所以b可以在O(n)时间,对于c,每找到一个w[x1]满足b的条件,则在树状数组中+1

w[x2].ans+=query(w[x2].c)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 struct Node
 7 {
 8     int a,b,c,cnt,ans;
 9 }w[100001];
10 int m,n,c[2000001],ans,f[100001];
11 bool cmp2(Node a,Node b)
12 {
13     if (a.b==b.b)
14      return a.c<b.c;
15      else return a.b<b.b;
16 }
17 bool cmp1(Node a,Node b)
18 {
19     if (a.a==b.a)
20      return cmp2(a,b);
21      else return a.a<b.a;
22 }
23 void add(int x,int d)
24 {
25     while (x<=m)
26     {
27      c[x]+=d;
28      x+=(x&(-x));
29     }
30 }
31 int query(int x)
32 {int s=0;
33     while (x)
34     {
35      s+=c[x];
36      x-=(x&(-x));
37     }
38   return s;
39 }
40 void cdq(int l,int r)
41 {int r1,r2;
42     int mid=(l+r)/2;
43     if (l==r)
44     return;
45      cdq(l,mid);cdq(mid+1,r);
46      sort(w+l,w+mid+1,cmp2);
47      sort(w+mid+1,w+r+1,cmp2);
48      r1=l;r2=mid+1;
49      while (r2<=r)
50      {
51         while (r1<=mid&&w[r1].b<=w[r2].b)
52          add(w[r1].c,w[r1].cnt),r1++;
53          w[r2].ans+=query(w[r2].c);
54         r2++;
55      }
56     for (int i=l;i<=r1-1;i++)
57     add(w[i].c,-w[i].cnt);
58 }
59 int main()
60 {int i,j,num=0;
61     cin>>n>>m;
62     for (i=1;i<=n;i++)
63     {
64       scanf("%d%d%d",&w[i].a,&w[i].b,&w[i].c);
65       w[i].cnt=1;
66     }
67     sort(w+1,w+n+1,cmp1);
68     for (i=1;i<=n;i++)
69     {
70         int k=i+1;
71         while (w[i].a==w[k].a&&w[i].b==w[k].b&&w[i].c==w[k].c)
72          k++;
73          num++;
74          k--;
75          w[i].cnt+=k-i;
76          w[num]=w[i];
77          i=k;
78     }
79     cdq(1,num);
80     for (i=1;i<=num;i++)
81     f[w[i].ans+w[i].cnt-1]+=w[i].cnt;
82     for (i=0;i<n;i++)
83     printf("%d\n",f[i]);
84 }

 

posted @ 2017-08-21 18:56  Z-Y-Y-S  阅读(384)  评论(0编辑  收藏  举报