bzoj 3262 陌上花开 【CDQ分治】

三维偏序

首先把所有花按 x一序,y二序,z三序 排序,然后去重,con记录同样的花的个数,然后进行cdq

现在假设有[l.r]区间,其中[l,mid] [mid+1,r],已经递归处理完毕。我们把区间[l,mid] [mid+1,r]按 y一序,z二序,x三序 排序,那么现在所有[l,mid]区间里的x比所有[mid+1,r]区间里的x要小,并且在 [l,mid] [mid+1,r]中y是递增的。那么现在考虑[l,mid]中对[mid+1,r]中有贡献的个数,即只需要维护z的大小关系即可。对此用权值树状数组维护。

p.s. 在处理完区间之后对树状数组的清零操作不要用memset,直接update负值。这样能保证复杂度

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=100005,K=200005;
 6 int n,k,tot,t[K],ans[N];
 7 struct qwe
 8 {
 9     int x,y,z,con,ans;
10 }a[N];
11 bool cmp1(const qwe &a,const qwe &b)
12 {
13     return (a.x==b.x&&a.y==b.y&&a.z<b.z)||(a.x==b.x&&a.y<b.y)||(a.x<b.x);
14 }
15 bool cmp2(const qwe &a,const qwe &b)
16 {
17     return (a.y==b.y&&a.z==b.z&&a.x<b.x)||(a.y==b.y&&a.z<b.z)||(a.y<b.y);
18 }
19 int read()
20 {
21     int r=0,f=1;
22     char p=getchar();
23     while(p>'9'||p<'0')
24     {
25         if(p=='-')
26             f=-1;
27         p=getchar();
28     }
29     while(p>='0'&&p<='9')
30     {
31         r=r*10+p-48;
32         p=getchar();
33     }
34     return r*f;
35 }
36 int lb(int x)
37 {
38     return x&(-x);
39 }
40 void update(int x,int v)
41 {
42     for(int i=x;i<=k;i+=lb(i))
43         t[i]+=v;
44 }
45 int ques(int x)
46 {
47     int r=0;
48     for(int i=x;i>=1;i-=lb(i))
49         r+=t[i];
50     return r;
51 }
52 void cdq(int l,int r)
53 {
54     if(l==r)
55     {
56         a[l].ans+=a[l].con-1;
57         return;
58     }
59     int mid=(l+r)>>1;
60     cdq(l,mid);
61     cdq(mid+1,r);
62     sort(a+l,a+1+mid,cmp2);
63     sort(a+mid+1,a+1+r,cmp2);
64     int j=l;
65     for(int i=mid+1;i<=r;i++)
66     {
67         for(;j<=mid&&a[j].y<=a[i].y;j++)
68             update(a[j].z,a[j].con);
69         a[i].ans+=ques(a[i].z);
70     }
71     for(int i=l;i<j;i++)
72         update(a[i].z,-a[i].con);
73 }
74 int main()
75 {
76     n=read(),k=read();
77     for(int i=1;i<=n;i++)
78         a[i].x=read(),a[i].y=read(),a[i].z=read(),a[i].ans=1;
79     sort(a+1,a+1+n,cmp1);
80     for(int i=1;i<=n;i++)
81         if(i!=1&&a[i].x==a[i-1].x&&a[i].y==a[i-1].y&&a[i].z==a[i-1].z)
82             a[tot].con++;
83         else
84             a[++tot]=a[i],a[tot].con++;
85     cdq(1,tot);
86     for(int i=1;i<=tot;i++)
87         ans[a[i].ans]+=a[i].con;//cout<<n<<endl;
88     for(int i=1;i<=n;i++)
89         printf("%d\n",ans[i]);
90     return 0;
91 }

 

  

posted @ 2017-12-25 09:52  lokiii  阅读(150)  评论(0编辑  收藏  举报