BZOJ.3262.陌上花开([模板]CDQ分治 三维偏序)
2018-03-15 17:35
375 查看
题目链接 BZOJ3262
洛谷P3810
3.30:
洛谷P3810
/* 5904kb 872ms 对于相邻x,y,z相同的元素要进行去重,并记录次数算入贡献(它们之间产生的答案是一样的,但不去重会。。) */ #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar() #define lb(x) (x)&-(x) const int N=1e5+5; int n,Ans ; int read(); struct Operation { int x,y,z,cnt,res; inline void Init(){ x=read(),y=read(),z=read(),cnt=1; } bool operator <(const Operation &a)const{ return x==a.x?(y==a.y?z<a.z:y<a.y):x<a.x; } }q ,tmp ; namespace BIT {//三维:树状数组 int Max,t[N<<1]; void Add(int p,int v){ while(p<=Max) t[p]+=v,p+=lb(p); } int Query(int p){ int res=0; while(p) res+=t[p],p-=lb(p); return res; } } inline int read() { int now=0,f=1;register char c=gc(); for(;!isdigit(c);c=gc()) if(c=='-') f=-1; for(;isdigit(c);now=now*10+c-'0',c=gc()); return now*f; } void CDQ(int l,int r) {//处理第二维 if(l<r) { int m=l+r>>1; CDQ(l,m), CDQ(m+1,r); int p1=l,p2=m+1,cnt=0; while(p1<=m&&p2<=r) { if(q[p1].y<=q[p2].y)//这里的条件要是<= BIT::Add(q[p1].z,q[p1].cnt), tmp[cnt++]=q[p1++]; else q[p2].res+=BIT::Query(q[p2].z), tmp[cnt++]=q[p2++]; } while(p1<=m) BIT::Add(q[p1].z,q[p1].cnt), tmp[cnt++]=q[p1++];//先加上 方便再减去 while(p2<=r) q[p2].res+=BIT::Query(q[p2].z), tmp[cnt++]=q[p2++]; for(int i=l; i<=m; ++i) BIT::Add(q[i].z,-q[i].cnt); for(int i=0; i<cnt; ++i) q[l+i]=tmp[i]; } } int main() { n=read(),BIT::Max=read(); for(int i=1; i<=n; ++i) q[i].Init(); std::sort(q+1,q+1+n); int cnt=1; for(int i=2; i<=n; ++i) if(q[i].x==q[i-1].x&&q[i].y==q[i-1].y&&q[i].z==q[i-1].z) ++q[cnt].cnt; else q[++cnt]=q[i]; CDQ(1,cnt); for(int i=1; i<=cnt; ++i) Ans[q[i].res+q[i].cnt-1]+=q[i].cnt;//f[i]为res[i]+cnt[i]-1, 贡献为cnt[i] for(int i=0; i<n; ++i) printf("%d\n",Ans[i]); return 0; }
3.30:
/* 5904kb 840ms 是对x,y,z都相同的元素去重,不是对z。。sb了。 去重后的贡献是q[p].cnt! */ #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar() #define lb(x) (x)&-(x) const int N=1e5+5,MAXN=2e5+5; int n,Ans ; int read(); struct Node { int x,y,z,cnt,ans; void Init(){ x=read(),y=read(),z=read(),cnt=1; } bool operator <(const Node &a)const{ return x==a.x?(y==a.y?z<a.z:y<a.y):x<a.x; } }q ,tmp ; inline int read() { int now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } namespace BIT { int n,val[MAXN]; inline void Add(int p,int v){ while(p<=n) val[p]+=v,p+=lb(p); } inline int Query(int p){ int res=0; while(p) res+=val[p],p-=lb(p); return res; } inline void Clear(int p){ while(p<=n) if(val[p]) val[p]=0,p+=lb(p); else break; } } void CDQ(int l,int r) { if(l<r){ int m=l+r>>1; CDQ(l,m), CDQ(m+1,r); int p1=l,p2=m+1,t=0; while(p1<=m&&p2<=r) { if(q[p1].y<=q[p2].y) BIT::Add(q[p1].z,q[p1].cnt), tmp[t++]=q[p1++];//只是排y,别去管什么z。。 else q[p2].ans+=BIT::Query(q[p2].z), tmp[t++]=q[p2++]; } if(p1<=m){ for(int i=l; i<p1; ++i) BIT::Clear(q[i].z); while(p1<=m) tmp[t++]=q[p1++]; } else if(p2<=r){ while(p2<=r) q[p2].ans+=BIT::Query(q[p2].z), tmp[t++]=q[p2++]; for(int i=l; i<=m; ++i) BIT::Clear(q[i].z); } for(int i=0; i<t; ++i) q[l+i]=tmp[i]; } } int main() { n=read(),BIT::n=read(); for(int i=1; i<=n; ++i) q[i].Init(); std::sort(q+1,q+1+n); int cnt=1; for(int i=2; i<=n; ++i) if(q[i].z!=q[i-1].z||q[i].y!=q[i-1].y||q[i].x!=q[i-1].x) q[++cnt]=q[i]; else ++q[cnt].cnt; CDQ(1,cnt); for(int i=1; i<=cnt; ++i) Ans[q[i].ans+q[i].cnt-1]+=q[i].cnt; for(int i=0; i<n; ++i) printf("%d\n",Ans[i]); return 0; }
相关文章推荐
- CDQ分治--模板 BZOJ 3262--陌上花开【三维偏序】
- BZOJ - 3262 陌上花开 CDQ分治 三维偏序
- BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]
- BZOJ 3262 陌上花开、HDU 5618 Jam's problem again(三维偏序、cdq分治 + BIT)
- BZOJ 3262: 陌上花开 CDQ三维偏序,树套树,两种解法
- [bzoj] 3263 陌上花开 洛谷 P3810 三维偏序|| CDQ分治 && CDQ分治讲解
- 【三维偏序】【分块】bzoj3262 陌上花开
- BZOJ.1935.[SHOI2007]Tree园丁的烦恼(CDQ分治 三维偏序)
- 【BZOJ3295】动态逆序对(CQOI2011)-CDQ分治:三维偏序
- 【模板】三维偏序-cdq分治
- [BZOJ3262]陌上花开 三维偏序 CDQ分治+树状数组 模板
- 【BZOJ 3262】 陌上花开 CDQ分治 模板题
- [cdq分治] bzoj3262: 陌上花开
- bzoj3262陌上花开 cdq分治 三维偏序
- 【BZOJ 3262】陌上开花 CDQ分治
- Bzoj 3262: 陌上花开(CDQ分治)
- SPOJ:Another Longest Increasing Subsequence Problem(CDQ分治求三维偏序)
- BZOJ 3262 陌上花开 - CDQ分治
- 洛谷P3810(三维偏序,CDQ分治果题)
- bzoj 3262(cdq分治)