[BZOJ2253][2010 Beijing wc]纸箱堆叠(dp+bit+cdq分治)
2017-03-24 21:47
423 查看
题目描述
传送门题解
最长上升子序列+三维偏序问题裸的dp人人会对吧O(n2)
考虑对序列进行cdq分治,每一次用左边的区间来更新右边的区间
按照x分治,每一次按照y排序,然后z用树状数组查询
需要注意的是,这里全部都是严格大于,也就是说分治的时候划分到左右两边的点不能出现x相等的情况,这样的话就预处理一下然后在选中点的时候搞一搞就行了
并且更新的顺序必须是:递归左区间,处理左区间对右区间的影响,递归右区间
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 300005 int A,Mod,n,LSH,ans; int lsh ,L ,R ,C ,f ,ch ; struct data{int x,y,z,id;}q ,a ,b ; int cmp(data a,data b) { return a.x<b.x||(a.x==b.x&&a.y<b.y)||(a.x==b.x&&a.y==b.y&&a.z<b.z); } int cmpy(data a,data b) { return a.y<b.y; } void cover(int loc) { for (int i=loc;i<=LSH;i+=i&-i) C[i]=0; } void add(int loc,int val) { for (int i=loc;i<=LSH;i+=i&-i) C[i]=max(C[i],val); } int query(int loc) { int ans=0; for (int i=loc;i>=1;i-=i&-i) ans=max(ans,C[i]); return ans; } void cdq(int l,int r) { if (q[l].x==q[r].x) return; int mid=(l+r)>>1; if (L[mid]!=l) mid=L[mid]-1; else mid=R[mid]; cdq(l,mid); int tot=0; int pa=1,pb=1,acnt=0,bcnt=0; for (int i=l;i<=mid;++i) a[++acnt]=q[i]; for (int i=mid+1;i<=r;++i) b[++bcnt]=q[i]; sort(a+1,a+acnt+1,cmpy);sort(b+1,b+bcnt+1,cmpy); while (pb<=bcnt) { while (pa<=acnt&&a[pa].y<b[pb].y) { add(a[pa].z,f[a[pa].id]); ch[++tot]=a[pa].z; ++pa; } f[b[pb].id]=max(f[b[pb].id],query(b[pb].z-1)+1); ++pb; } for (int i=1;i<=tot;++i) cover(ch[i]); cdq(mid+1,r); } int main() { scanf("%d%d%d",&A,&Mod,&n);q[0].z=1; for (int i=1;i<=n;++i) { q[i].x=(long long)q[i-1].z*A%Mod,q[i].y=(long long)q[i].x*A%Mod; q[i].z=(long long)q[i].y*A%Mod; lsh[++LSH]=q[i].x,lsh[++LSH]=q[i].y,lsh[++LSH]=q[i].z; } for (int i=1;i<=n;++i) { if (q[i].x>q[i].y) swap(q[i].x,q[i].y); if (q[i].y>q[i].z) swap(q[i].y,q[i].z); if (q[i].x>q[i].y) swap(q[i].x,q[i].y); } sort(lsh+1,lsh+LSH+1);LSH=unique(lsh+1,lsh+LSH+1)-lsh-1; for (int i=1;i<=n;++i) q[i].x=lower_bound(lsh+1,lsh+LSH+1,q[i].x)-lsh, q[i].y=lower_bound(lsh+1,lsh+LSH+1,q[i].y)-lsh, q[i].z=lower_bound(lsh+1,lsh+LSH+1,q[i].z)-lsh; sort(q+1,q+n+1,cmp); for (int i=1;i<=n;++i) q[i].id=i; for (int i=1;i<=n;++i) if (i==1||q[i].x!=q[i-1].x) L[i]=i; else L[i]=L[i-1]; for (int i=n;i>=1;--i) if (i==n||q[i].x!=q[i+1].x) R[i]=i; else R[i]=R[i+1]; f[q[1].id]=1; cdq(1,n); for (int i=1;i<=n;++i) ans=max(ans,f[i]); printf("%d\n",ans); }
相关文章推荐
- bzoj 2253: [2010 Beijing wc]纸箱堆叠 (CDQ分治+DP)
- [BZOJ2253][2010 Beijing wc]纸箱堆叠(CDQ分治优化DP)
- [BZOJ 2253][2010 Beijing wc]纸箱堆叠:CDQ分治|DP
- 【BZOJ2253】[2010 Beijing wc]纸箱堆叠 cdq分治
- bzoj2253: [2010 Beijing wc]纸箱堆叠
- BZOJ_2253_[2010 Beijing wc]纸箱堆叠 _CDQ分治+树状数组
- 【BZOJ】2253: [2010 Beijing wc]纸箱堆叠
- BZOJ2253: [2010 Beijing wc]纸箱堆叠
- bzoj2253 [2010 Beijing wc]纸箱堆叠(cdq分治+树状数组)
- 2253: [2010 Beijing wc]纸箱堆叠
- 【BZOJ】【2253】【WC 2010 BeijingWC】纸箱堆叠
- [BZOJ2253][2010BJWC]纸箱堆叠(dp+cdq分治)
- BZOJ 2253 纸箱堆叠(CDQ分治)
- 【BZOJ2253】纸箱堆叠 [CDQ分治]
- 纸箱堆叠 BZOJ 2253
- BZOJ2253 [2010 Beijing wc]纸箱堆叠
- BZOJ2253 2010 Beijing wc 纸箱堆叠 CDQ分治
- bzoj2253 [2010 Beijing wc]纸箱堆叠(CDQ+dp)
- 【BZOJ2253】纸箱堆叠
- BZOJ 2251 Beijing WC 2010 外星联络 后缀数组