打铁选手的 CDQ分治 刷题记录

BZOJ3262

  • 模板题,三位偏序。
  • 注意第一维排完序之后再给二三维排序的时候还是要考虑下第一维的:如果二三维都相等的话第一维小的要在前面
  • 代码:
     1 #include <bits/stdc++.h>
     2 #define nmax 1000100
     3 #define lowbit(x) x&(-x)
     4  
     5 using namespace std;
     6 struct point{
     7     int x,y,z;
     8     bool operator == (const point& c) const { return (c.x==x)&&(c.y==y)&&(c.z==z); }
     9 };
    10 point in[nmax],a[nmax];
    11 int n,k;
    12 int p[nmax],c[nmax]={0},v[nmax]={0},an[nmax]={0},fa[nmax]={0};
    13  
    14 bool cmp1(point c,point b){
    15     if(c.x==b.x) return (c.y==b.y)?(c.z<b.z):(c.y<b.y);
    16     else return c.x<b.x;
    17 }
    18  
    19 bool cmp2(int b,int c){
    20     if(a[b].y==a[c].y) return (a[b].z==a[c].z)?(a[b].x<a[c].x):(a[b].z<a[c].z);
    21     return a[b].y<a[c].y;  //第二次排序的时候也是要考虑a的
    22 }
    23  
    24 inline void addv(int x,int t){
    25     while(x<=k){ c[x]+=t; x+=lowbit(x); }
    26 }
    27  
    28 inline int f(int x){
    29     int ans=0;
    30     while(x>0) { ans+=c[x]; x-=lowbit(x); }
    31     return ans;
    32 }
    33  
    34 void solve(int l,int r){
    35     if(l==r) { an[l]+=(v[l]-1); return; }
    36     int ans=0,mid=(l+r)/2;
    37     for (int i=l; i<=r; i++) p[i]=i;
    38     sort(p+l,p+r+1,cmp2);
    39     for (int i=l; i<=r; i++) {
    40         int id=p[i];
    41         if(id<=mid) addv(a[id].z,v[id]); //在左边
    42         else {
    43                 an[id]+=f(a[id].z);   //在右边
    44  //               printf("now an[%d]=%d \n",id,an[id]);
    45         }
    46     }
    47     //清空树状数组
    48     for (int i=l; i<=r; i++) {
    49             int id=p[i];
    50             if(id<=mid) addv(a[id].z,(-1)*v[id]);
    51     }
    52     solve(l,mid);
    53     solve(mid+1,r);
    54 }
    55  
    56 int main(){
    57     scanf("%d%d",&n,&k);
    58     for (int i=1; i<=n; i++) scanf("%d%d%d",&in[i].x,&in[i].y,&in[i].z);
    59     sort(in+1,in+n+1,cmp1);
    60     //去重
    61     int cnt=0,i=1,j=2;
    62     while (i<=n){
    63         a[++cnt]=in[i];
    64         v[cnt]=1;
    65         while(in[i]==in[j]) { j++; v[cnt]++; }
    66         i=j; j++;
    67     }
    68     //去重 over 要处理的数组是a
    69     solve(1,cnt);
    70     for (int i=1; i<=cnt; i++) fa[an[i]]+=v[i];
    71     for (int i=0; i<n; i++) printf("%d\n",fa[i]);
    72     return 0;
    73 }
    030

     

posted @ 2019-08-08 17:25  连昵称都不能重复  阅读(132)  评论(0编辑  收藏  举报