bzoj 3262: 陌上花开(cdq分治)
2016-09-08 19:26
423 查看
3262: 陌上花开
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1431 Solved: 644
[Submit][Status][Discuss]
Description
有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),又三个整数表示。现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb。显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。Input
第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性
Output
包含N行,分别表示评级为0...N-1的每级花的数量。Sample Input
10 33 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
Sample Output
31
3
0
1
0
1
0
0
1
HINT
1 <= N <= 100,000, 1 <= K <= 200,000Source
树套树 CDQ分治[Submit][Status][Discuss]
题解:cdq分治。
这道题我刚开始是想能不能把三个值搞到一块,然后每次判断只需要对比这个值即可,但是想了很久都没想出来。
那要怎么做呢?我们按照s权值从小到大排序,然后二分s权值区间[l,r],找到权值在[l,r]的区间[x,y],在二分一个中间权值mid,利用二分查找找到值为mid的最后一个数的位置,因为a是从小到大有序的所以只可能是[x,posmid]对后面[posmid+1,y]产生贡献且保证a一定满足条件,所以我们把前面的区间中的数标记,然后按照[x,y]中的数按照c权值从小到大排序,然后按照b的顺序如果有标记就向权值线段树的a[i].m的位置加数,如果没有标记就统计权值线段树中[1,a[i].m]的答案然后添加到ans[a[i].num]。注意那些b,c都相等的花,要放到一起考虑,要一起都加入后再计算。
细节很多,尤其是二分查找!!
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #define N 200003 using namespace std; struct data { int a,b,c,num; int pd; }a ; int n,m,tr[N*4],pd[N*4],minn,maxn,num ; int ans ; void clear(int now) { tr[now]=0; pd[now]=1; } int cmp(data a,data b) { return a.a<b.a; } int cmp1(data a,data b) { return a.b<b.b||a.b==b.b&&a.c<b.c; } void pushdown(int now) { if (pd[now]) { pd[now]=0; clear(now<<1); clear(now<<1|1); } } void update(int now) { tr[now]=tr[now<<1]+tr[now<<1|1]; } void pointchange(int now,int l,int r,int x) { if (l==r) { tr[now]++; return; } pushdown(now); int mid=(l+r)/2; if (x<=mid) pointchange(now<<1,l,mid,x); else pointchange(now<<1|1,mid+1,r,x); update(now); } int qjsum(int now,int l,int r,int ll,int rr) { if (ll<=l&&r<=rr) return tr[now]; pushdown(now); int mid=(l+r)/2; int ans=0; if (ll<=mid) ans+=qjsum(now<<1,l,mid,ll,rr); if (rr>mid) ans+=qjsum(now<<1|1,mid+1,r,ll,rr); return ans; } int find(int x,int l,int r) { int ans=r; int nowr=r,nowl=l; if (a[l].a>x) return l; if (a[r].a<x) return r+1; while (l<=r) { int mid=(l+r)/2; if (a[mid].a>=x) ans=min(ans,mid),r=mid-1; else l=mid+1; } return ans; } void divide(int l,int r,int x,int y) { bool f=true; for (int i=x+1;i<=y;i++) if (a[i].a!=a[x].a) { f=false; break; } if (l>r||x>y) return; if (l==r||x==y||f) { sort(a+x,a+y+1,cmp1); clear(1); for (int i=x;i<=y;i++) if (a[i].c!=a[i+1].c||i==y||a[i].b!=a[i+1].b) { pointchange(1,1,m,a[i].c); int j=i; while (a[j].c==a[i].c&&a[j].b==a[i].b&&j>=x) { int t=qjsum(1,1,m,1,a[j].c); ans[a[j].num]+=t; j--; } } else pointchange(1,1,m,a[i].c); return ; } int mid=(l+r)/2; int posf=x; int pose=y; int posm=find(mid+1,x,y)-1; clear(1); for (int i=posf;i<=posm;i++) a[i].pd=1; for (int i=posm+1;i<=pose;i++) a[i].pd=0; sort(a+posf,a+pose+1,cmp1); for (int i=posf;i<=pose;i++) if (a[i].c!=a[i+1].c||a[i].b!=a[i+1].b||i==pose) { if (a[i].pd==1) pointchange(1,1,m,a[i].c); int j=i; while (a[j].c==a[i].c&&a[j].b==a[i].b&&j>=x) { if (a[j].pd==0) { int t=qjsum(1,1,m,1,a[j].c); ans[a[j].num]+=t; } j--; } } else if (a[i].pd==1) pointchange(1,1,m,a[i].c); sort(a+posf,a+pose+1,cmp); divide(l,mid,posf,posm); divide(mid+1,r,posm+1,pose); } int main() { freopen("a.in","r",stdin); freopen("my.out","w",stdout); scanf("%d%d",&n,&m); minn=N,maxn=0; for (int i=1;i<=n;i++) scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c),a[i].num=i, minn=min(minn,a[i].a),maxn=max(maxn,a[i].a); sort(a+1,a+n+1,cmp); divide(1,maxn,1,n); for (int i=1;i<=n;i++) num[ans[i]]++; for (int i=1;i<=n;i++) printf("%d\n",num[i]); }
相关文章推荐
- 【CDQ分治】 BZOJ3262 陌上花开
- BZOJ 3262 陌上花开 (CDQ分治)
- cdq分治入门--BZOJ3262: 陌上花开
- 【BZOJ3262】陌上花开 cdq分治
- BZOJ 3262 陌上花开、HDU 5618 Jam's problem again(三维偏序、cdq分治 + BIT)
- BZOJ 3262 陌上花开 - CDQ分治
- BZOJ 3262 陌上花开 树套树 (CDQ分治)
- BZOJ - 3262 陌上花开 CDQ分治 三维偏序
- 【BZOJ 3262】 陌上花开 CDQ分治 模板题
- CDQ分治--模板 BZOJ 3262--陌上花开【三维偏序】
- BZOJ 3262: 陌上花开 CDQ分治
- bzoj 3262: 陌上花开 【cdq分治】
- [CDQ分治] [树状数组] [BZOJ3262] 陌上花开
- bzoj 3262: 陌上花开 (cdq分治)
- 【BZOJ3262】陌上花开(CDQ分治)
- BZOJ 3262 陌上花开 CDQ分治
- bzoj 3262: 陌上花开(cdq分治)
- bzoj 3262 陌上花开 【CDQ分治】
- 【BZOJ 3262】 3262: 陌上花开 (CDQ分治)
- Bzoj 3262: 陌上花开(CDQ分治)