bzoj 3263 陌上花开(cdq分治,BIT)
【题意】
求满足Ai<=Aj,Bi<=Bj,Ci<=Cj的数对的数目。
【思路】
cdq分治
借网上一句话:第一维排序,第二维cdq分治,第三维树状数组维护。
首先合并三维都是相同的项。
先按照第一维排序然后cdq分治。
定义solve(l,r)为解决区间l,r内所有询问且solve结束后区间有序,设mid=(l+r)/2,
1) Solve(l,mid)
2) Solve(mid+1,r)
//因为经过第一维排序,所以左区间的a都小于等于右区间的a。
3) 处理跨立影响。因为已经排过序,所以左区间的a都要小于右区间的a,因为solve后区间有序,所以左右区间都各自按照b排好了序。按照归并排序的思路,计算左区间对每一个右区间内点的贡献:处理到右区间的l2时,将所有左区间内比他的b小的加入BIT,这时候只要查询一次就可以得出左区间对l2的贡献。
4) 清理BIT,并按照b c大小将左右区间合并使区间有序
最后根据题目要求转化一下。
总的时间为O(nlog^2n),bingo
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 3*1e5+10; 8 9 struct Node { 10 int a,b,c,s,ans; 11 }que[N],a[N]; 12 13 bool cmp1(const Node& x,const Node& y) { 14 return x.b<y.b||(x.b==y.b&&x.c<y.c); 15 } 16 bool cmp2(const Node& x,const Node& y) { 17 if(x.a==y.a&&x.b==y.b) return x.c<y.c; 18 else if(x.a==y.a) return x.b<y.b; 19 else return x.a<y.a; 20 } 21 22 int n,K,C[N],ans[N]; 23 24 void add(int x,int v) 25 { 26 for(;x<=K;x+=x&-x) C[x]+=v; 27 } 28 int query(int x) 29 { 30 int res=0; 31 for(;x;x-=x&-x) res+=C[x]; 32 return res; 33 } 34 Node t[N]; 35 void solve(int l,int r) 36 { 37 if(l==r) return ; 38 int mid=(l+r)>>1; 39 solve(l,mid) , solve(mid+1,r); 40 int l1=l,l2=mid+1; 41 while(l2<=r) { 42 while(l1<=mid && que[l1].b<=que[l2].b) { 43 add(que[l1].c,que[l1].s); 44 l1++; 45 } 46 que[l2].ans+=query(que[l2].c); 47 l2++; 48 } 49 for(int i=l;i<l1;i++) 50 add(que[i].c,-que[i].s); 51 l1=l,l2=mid+1; int pos=l; 52 while(l1<=mid||l2<=r) { 53 if(l2>r||(l1<=mid&&cmp1(que[l1],que[l2]))) t[pos++]=que[l1++]; 54 else t[pos++]=que[l2++]; 55 } 56 for(int i=l;i<=r;i++) que[i]=t[i]; 57 } 58 void read(int& x) 59 { 60 char c=getchar(); x=0; 61 while(!isdigit(c)) c=getchar(); 62 while(isdigit(c)) x=x*10+c-'0',c=getchar(); 63 } 64 int main() 65 { 66 //freopen("in.in","r",stdin); 67 //freopen("out.out","w",stdout); 68 read(n),read(K); 69 for(int i=1;i<=n;i++) 70 read(a[i].a),read(a[i].b),read(a[i].c); 71 sort(a+1,a+n+1,cmp2); 72 int cnt=0,sz=0; 73 for(int i=1;i<=n;i++) { 74 cnt++; 75 if(a[i].a!=a[i+1].a||a[i].b!=a[i+1].b||a[i].c!=a[i+1].c) 76 { 77 que[++sz]=a[i]; 78 que[sz].s=cnt; 79 cnt=0; 80 } 81 } 82 solve(1,sz); 83 for(int i=1;i<=sz;i++) 84 ans[que[i].ans+que[i].s-1]+=que[i].s; 85 //评级为0~n-1的每级花的数量 86 for(int i=0;i<n;i++) 87 printf("%d\n",ans[i]); 88 return 0; 89 }
posted on 2016-03-08 16:43 hahalidaxin 阅读(979) 评论(0) 编辑 收藏 举报