CDQ分治


P3810 【模板】三维偏序(陌上花开)

题目背景

这是一道模板题

可以使用bitset,CDQ分治,K-DTree等方式解决。

题目描述

有 n 个元素,第 i个元素有 aibici 三个属性,设 f(i)f表示满足ajai 且bjbi 且 cjci 的 j的数量。

对于 d[0,n),求 f(i)=d 的数量

输入格式

第一行两个整数 nk,分别表示元素数量和最大属性值。

之后 n 行,每行三个整数 aibici,分别表示三个属性值。

输出格式

输出 n行,第 d + 1行表示 f(i) = d的 i 的数量。

输入输出样例

输入 #1复制
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
输出 #1复制
3
1
3
0
1
0
1
0
0
1

说明/提示

1n100000,1k200000

       板子题,思想类似于归并排。

      

  1 // luogu-judger-enable-o2
  2 #include<bits/stdc++.h>
  3 #define re register int
  4 #define lowbit(x) x&(-x)
  5 #define LL long long
  6 const int maxn1=100000+5;
  7 const int maxn2=200000+5;
  8 using namespace std;
  9 int tree[maxn2];
 10 int cnt[maxn2];
 11 int n,k;
 12 inline int read()
 13 {
 14     int x=0,f=1;
 15     char ch=getchar();
 16     while(!isdigit(ch))
 17     {
 18         if(ch=='-') f=-1;
 19         ch=getchar();
 20     }
 21     while(isdigit(ch))
 22     {
 23         x=(x<<3)+(x<<1)+ch-'0';
 24         ch=getchar();
 25     }
 26     return x*f;
 27 }
 28 inline void write(int x)
 29 {
 30     if(x<0)
 31     {
 32         putchar('-');
 33         x=-x; 
 34     }
 35     if(x>9) write(x/10);
 36     putchar(x%10+'0');
 37 }
 38 struct node{
 39     int x,y,z,ans,w;
 40 };
 41 node no[maxn1],ed[maxn1];
 42 bool cmpx(const node &a,const node&b)
 43 {
 44     if(a.x!=b.x)  return a.x<b.x;
 45     if(a.y!=b.y)  return a.y<b.y;
 46     else return a.z<b.z;
 47 }
 48 bool cmpy(const node &a,const node&b)
 49 {
 50     if(a.y!=b.y)  return a.y<b.y;
 51     else return a.z<b.z;
 52 }
 53 void add(int pos,int val)
 54 {
 55     while(pos<=k)
 56     {
 57         tree[pos]+=val;
 58         pos+=lowbit(pos);
 59     }
 60 }
 61 int Query(int pos)
 62 {
 63     int ans=0;
 64     while(pos)
 65     {
 66         ans+=tree[pos];
 67         pos-=lowbit(pos);
 68     }
 69     return ans;
 70 }
 71 void cdq(int l,int r)
 72 {
 73     if(l==r) return;
 74     int mid=(l+r)>>1;
 75     cdq(l,mid);
 76     cdq(mid+1,r);
 77     sort(no+l,no+mid+1,cmpy);
 78     sort(no+mid+1,no+r+1,cmpy);
 79     int i=mid+1,j=l;
 80     for(;i<=r;i++)
 81     {
 82         while(no[j].y<=no[i].y&&j<=mid)
 83     {
 84         add(no[j].z,no[j].w);
 85         j++;}
 86         no[i].ans+=Query(no[i].z);
 87     }
 88     for(i=l;i<j;i++)
 89     add(no[i].z,-no[i].w);
 90 }
 91 int cou;
 92 int main()
 93 {
 94     n=read();
 95     k=read();
 96     for(re i=1;i<=n;i++)
 97     {
 98         ed[i].x=read();
 99         ed[i].y=read();
100         ed[i].z=read();
101     }
102     sort(ed+1,ed+n+1,cmpx);
103     int sum=0;
104     for(re i=1;i<=n;i++)
105     {
106         sum++;
107         if(ed[i].x!=ed[i+1].x||ed[i].y!=ed[i+1].y||ed[i].z!=ed[i+1].z)
108         {
109             no[++cou]=ed[i];
110             no[cou].w=sum;
111             sum=0;
112         }
113     }
114     cdq(1,cou);
115     for(re i=1;i<=cou;i++)
116     cnt[no[i].ans+no[i].w-1]+=no[i].w;
117     for(re i=0;i<n;i++)
118     {write(cnt[i]);
119     putchar('\n');}
120     return 0;
121     }
View Code

 

转载于:https://www.cnblogs.com/3200Pheathon/p/11598570.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值