题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3262
题目大意:中文题目
具体思路:CDQ可以处理的问题,一共有三维空间,对于第一维我们直接按照从小到大排序就可以了,然后就开始处理第二维,第二维的话我们通过cdq来维护,然后第三维通过树状数组维护就可以了。
刚开始做CDQ的问题,个人觉得CDQ处理的就是把一整个大的问题转换成多个子问题进行求解,然后很重要的一个的地方就是解决前面一个子问题对后面的问题的影响。
AC代码:
1 #include<iostream> 2 #include<stack> 3 #include<stdio.h> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 # define ll long long 8 # define inf 0x3f3f3f3f 9 const int maxn = 2e5+100; 10 struct node{ 11 int x,y,z; 12 int ans,cnt; 13 }q[maxn]; 14 int maxstate; 15 bool cmp1(node t1,node t2){ 16 if(t1.x!=t2.x)return t1.x<t2.x; 17 if(t1.y!=t2.y)return t1.y<t2.y; 18 return t1.z<t2.z; 19 } 20 bool cmp2(node t1,node t2){ 21 if(t1.y!=t2.y)return t1.y<t2.y; 22 return t1.z<t2.z; 23 }//注意两个cmp的不同,对于第一个cmp我们只是初始的状态,但是对于第二个cmp,我们处理的是x已经排好的前提下了,如果这个时候再对q进行排序的话,会打乱y的正常顺序。 24 int vis[maxn],tree[maxn<<2]; 25 int lowbit(int x){return x&(-x);} 26 void update(int x,int val){ 27 while(x<=maxstate){ 28 tree[x]+=val; 29 x+=lowbit(x); 30 } 31 } 32 int ask(int x){ 33 int ans=0; 34 while(x){ 35 ans+=tree[x]; 36 x-=lowbit(x); 37 } 38 return ans; 39 } 40 void cdq(int l,int r){ 41 if(l==r){ 42 q[l].ans+=q[l].cnt-1; 43 return ; 44 } 45 int mid=(l+r)>>1; 46 cdq(l,mid); 47 cdq(mid+1,r); 48 sort(q+l,q+mid+1,cmp2); 49 sort(q+mid+1,q+r+1,cmp2); 50 int tmp=l; 51 for(int i=mid+1;i<=r;i++){ 52 while(tmp<=mid&&q[i].y>=q[tmp].y){ 53 update(q[tmp].z,q[tmp].cnt),tmp++; 54 } 55 q[i].ans+=ask(q[i].z); 56 } 57 for(int i=l;i<tmp;i++){ 58 update(q[i].z,-q[i].cnt); 59 }//消除前面一个子问题对后面的子问题的影响 60 } 61 int main(){ 62 //freopen("hqx.in","r",stdin); 63 int n; 64 scanf("%d %d",&n,&maxstate); 65 for(int i=1;i<=n;i++){ 66 scanf("%d %d %d",&q[i].x,&q[i].y,&q[i].z); 67 q[i].cnt=1; 68 q[i].ans=0; 69 } 70 int tot=0; 71 sort(q+1,q+n+1,cmp1); 72 for(int i=1;i<=n;i++){ 73 if(i!=1&&q[i].x==q[tot].x&&q[i].y==q[tot].y&&q[i].z==q[tot].z)q[tot].cnt++; 74 else q[++tot]=q[i]; 75 } 76 cdq(1,tot); 77 for(int i=1;i<=tot;i++){ 78 vis[q[i].ans]+=q[i].cnt; 79 } 80 for(int i=0;i<n;i++){ 81 printf("%d\n",vis[i]); 82 } 83 return 0; 84 }