陌上开花(CDQ分治)
题解
三维偏序裸题。。。
一般三维偏序是第一维排序,第二维CDQ分治,第三维树状数组。
模板题还是看代码吧。。。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int N=200100; 8 const int M=200100; 9 int n,d,tr[M],ans[N]; 10 struct query{ 11 int a,b,c; 12 int w,ans; 13 bool operator <(const query &x)const{ 14 if(x.a==a){ 15 if(x.b==b)return x.c>c; 16 else return x.b>b; 17 } 18 else return x.a>a; 19 } 20 }q[N],c[N]; 21 int lowbit(int x){ 22 return x&-x; 23 } 24 void add(int x,int w){ 25 for(int i=x;i<=N-100;i+=lowbit(i)){ 26 tr[i]+=w; 27 } 28 } 29 int getsum(int x){ 30 int ans=0; 31 for(int i=x;i>=1;i-=lowbit(i)){ 32 ans+=tr[i]; 33 } 34 return ans; 35 } 36 void cdq(int l,int r){ 37 if(l==r)return; 38 int mid=(l+r)>>1; 39 cdq(l,mid);cdq(mid+1,r); 40 int ll=l; 41 int rl=mid+1; 42 int now=0; 43 while(ll<=mid&&rl<=r){ 44 if(q[ll].b<=q[rl].b){ 45 add(q[ll].c,q[ll].w); 46 c[++now]=q[ll++]; 47 } 48 else{ 49 q[rl].ans+=getsum(q[rl].c); 50 c[++now]=q[rl++]; 51 } 52 } 53 while(ll<=mid){ 54 add(q[ll].c,q[ll].w); 55 c[++now]=q[ll++]; 56 } 57 while(rl<=r){ 58 q[rl].ans+=getsum(q[rl].c); 59 c[++now]=q[rl++]; 60 } 61 for(int i=l;i<=mid;i++)add(q[i].c,-q[i].w); 62 for(int i=l;i<=r;i++){ 63 q[i]=c[i-l+1]; 64 } 65 } 66 int main(){ 67 scanf("%d%d",&n,&d); 68 for(int i=1;i<=n;i++){ 69 scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].c); 70 q[i].w=1; 71 } 72 sort(q+1,q+1+n); 73 // for(int i=1;i<=n;i++){ 74 // cout<<q[i].a<<" "<<q[i].b<<" "<<q[i].c<<endl; 75 // } 76 int pd=1; 77 for(int i=2;i<=n;i++){ 78 if(q[pd].a==q[i].a&&q[pd].b==q[i].b&&q[pd].c==q[i].c)q[pd].w++; 79 else q[++pd]=q[i]; 80 } 81 int num=n; 82 n=pd; 83 cdq(1,pd); 84 for(int i=1;i<=n;i++)ans[q[i].ans+q[i].w]+=q[i].w; 85 for(int i=1;i<=num;i++)printf("%d\n",ans[i]); 86 return 0; 87 }