1. 程式人生 > >bzoj3262 陌上花開 cdq分治(入門)

bzoj3262 陌上花開 cdq分治(入門)

題目傳送門

思路:cdq分治處理偏序關係的模板題,主要就是學cdq分治吧,還在入門中。

  程式碼其實也很好理解,記得樹狀陣列操作的上限是 z的最大值,不是n的最大值,這個細節wa了好久。

#include<bits/stdc++.h>
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=100010;
struct node{
    int x,y,z,id;
    node(){}
    node(int x,int y,int z,int
id):x(x),y(y),z(z),id(id){} }a[maxn],b[maxn]; int ans[maxn],bit[maxn<<1],pr[maxn]; int n,k,maxd; inline void add(int x,int v){ while(x<=maxd){//切記 上限不是n,是z的最大值 bit[x]+=v; x+= x & -x; } } inline int sum(int x){ int ces=0; while(x>0){ ces+=bit[x]; x
-= x & -x; } return ces; } bool cmpall(const node &a,const node &b){ if(a.x!=b.x)return a.x<b.x; if(a.y!=b.y)return a.y<b.y; return a.z<b.z; } bool cmpy(const node &a,const node &b){ if(a.y!=b.y)return a.y<b.y; return a.id<b.id; } inline
void cdq(int l,int r){ if(l==r)return ; int mid=(l+r)>>1; int cc=0; for(int i=l;i<=mid;i++) { b[++cc]=a[i]; b[cc].id=0,b[cc].x=0; } for(int i=mid+1;i<=r;i++) { b[++cc]=a[i],b[cc].x=0; } sort(b+1,b+1+cc,cmpy); for(int i=1;i<=cc;i++) { if(b[i].id==0){ add(b[i].z,1); }else{ ans[b[i].id]+=sum(b[i].z); } } for(int i=1;i<=cc;i++) { if(b[i].id==0)add(b[i].z,-1); } cdq(l,mid),cdq(mid+1,r); return ; } int main(){ cin>>n>>k; for(int i=1;i<=n;i++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); maxd=max(maxd,a[i].z); a[i].id=i; } sort(a+1,a+1+n,cmpall); int cnt=0; for(int i=n;i>=1;i--) { if(a[i].x==a[i+1].x&&a[i].y==a[i+1].y&&a[i].z==a[i+1].z) { cnt++; }else cnt=0; ans[a[i].id]+=cnt; } cdq(1,n); for(int i=1;i<=n;i++) { pr[ans[i]]++; } for(int i=0;i<n;i++) { printf("%d\n",pr[i]); } }