BZOJ 2253 纸箱堆叠(CDQ分治)
2016-04-07 10:06
351 查看
Description
P 工厂是一个生产纸箱的工厂。纸箱生产线在人工输入三个参数 n p a , , 之后,即可自动化生产三边边长为
(a mod P,a^2 mod p,a^3 mod P)
(a^4 mod p,a^5 mod p,a^6 mod P)
….
(a^(3n-2) mod p,a^(3n-1) mod p,a^(3n) mod p)
的n个纸箱。在运输这些纸箱时,为了节约空间,必须将它们嵌套堆叠起来。一个纸箱可以嵌套堆叠进另一个纸箱当且仅当它的最短边、次短边和最长边长度分别严格小于另一个纸箱的最短边、次短边和最长边长度。这里不考虑任何旋转后在对角线方向的嵌套堆叠。你的任务是找出这n个纸箱中数量最多的一个子集,使得它们两两之间都可嵌套堆叠起来。
Input
输入文件的第一行三个整数,分别代表 a,p,n
Output
输出文件仅包含一个整数,代表数量最多的可嵌套堆叠起来的纸箱的个数
Sample Input
10 17 4
Sample Output
2
Solution
三维LIS问题,CDQ分治,按第一维x排序,由于此处是严格上升,故在分治过程中mid值需要使得[l,,mid]的第一维严格小于[mid+1,r]的第一维,以dp[i]表示以第i个元素结尾的LIS长度,则有dp[i]=max(dp[i],dp[j]+1),其中mid+1<=i<=r,l<=j<=mid,yj < yi,zj < zi,如果对[l,mid]和[mid+1,r]都按y为第一关键字,z为第二关键字升序排,每次计算dp[i]之前将所有满足yj < yi的j都以zj为下标,dp[j]为键值插入到树状数组中,那么问题转化为求树状数组中下标小于zi的最大值,最后的答案为max(dp[i])
Code
P 工厂是一个生产纸箱的工厂。纸箱生产线在人工输入三个参数 n p a , , 之后,即可自动化生产三边边长为
(a mod P,a^2 mod p,a^3 mod P)
(a^4 mod p,a^5 mod p,a^6 mod P)
….
(a^(3n-2) mod p,a^(3n-1) mod p,a^(3n) mod p)
的n个纸箱。在运输这些纸箱时,为了节约空间,必须将它们嵌套堆叠起来。一个纸箱可以嵌套堆叠进另一个纸箱当且仅当它的最短边、次短边和最长边长度分别严格小于另一个纸箱的最短边、次短边和最长边长度。这里不考虑任何旋转后在对角线方向的嵌套堆叠。你的任务是找出这n个纸箱中数量最多的一个子集,使得它们两两之间都可嵌套堆叠起来。
Input
输入文件的第一行三个整数,分别代表 a,p,n
Output
输出文件仅包含一个整数,代表数量最多的可嵌套堆叠起来的纸箱的个数
Sample Input
10 17 4
Sample Output
2
Solution
三维LIS问题,CDQ分治,按第一维x排序,由于此处是严格上升,故在分治过程中mid值需要使得[l,,mid]的第一维严格小于[mid+1,r]的第一维,以dp[i]表示以第i个元素结尾的LIS长度,则有dp[i]=max(dp[i],dp[j]+1),其中mid+1<=i<=r,l<=j<=mid,yj < yi,zj < zi,如果对[l,mid]和[mid+1,r]都按y为第一关键字,z为第二关键字升序排,每次计算dp[i]之前将所有满足yj < yi的j都以zj为下标,dp[j]为键值插入到树状数组中,那么问题转化为求树状数组中下标小于zi的最大值,最后的答案为max(dp[i])
Code
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define maxn 111111 int A,P,n,t[maxn],tot; struct node { int x,y,z,ans; void init(int a,int b,int c) { if(a>b)swap(a,b); if(a>c)swap(a,c); if(b>c)swap(b,c); x=a,y=b,t[++tot]=z=c,ans=1; } }p[maxn]; int cmpx(node a,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; } int cmpy(node a,node b) { if(a.y!=b.y)return a.y<b.y; return a.z<b.z; } struct BIT { #define lowbit(x) (x&(-x)) int b[maxn]; void init() { memset(b,0,sizeof(b)); } void update(int x,int v) { while(x<=n) { b[x]=max(b[x],v); x+=lowbit(x); } } int query(int x) { int ans=0; while(x) { ans=max(ans,b[x]); x-=lowbit(x); } return ans; } void clear(int x) { while(x<=n) { b[x]=0; x+=lowbit(x); } } }bit; void CDQ(int l,int r) { if(l>=r)return ; //保证[l,mid]的第一维严格小于[mid+1,r]的第一维 int mid=-1,tl=(l+r)>>1,tr=tl+1; while(tl>=l||tr<=r) { if(tl>=l&&p[tl].x!=p[tl+1].x) { mid=tl; break; } if(tr<=r&&p[tr-1].x!=p.x) { mid=tr-1; break; } tl--,tr++; } if(mid==-1)return ; CDQ(l,mid); sort(p+l,p+mid+1,cmpy); sort(p+mid+1,p+r+1,cmpy); for(int i=mid+1,j=l;i<=r;i++) { for(;j<=mid&&p[j].y<p[i].y;j++) bit.update(p[j].z,p[j].ans); p[i].ans=max(p[i].ans,bit.query(p[i].z-1)+1); } for(int i=l;i<=mid;i++)bit.clear(p[i].z); sort(p+mid+1,p+r+1,cmpx); CDQ(mid+1,r); } int main() { scanf("%d%d%d",&A,&P,&n); tot=0,bit.init(); int x,y,z,temp=1; for(int i=1;i<=n;i++) { x=temp=1ll*A*temp%P; y=temp=1ll*A*temp%P; z=temp=1ll*A*temp%P; p[i].init(x,y,z); } sort(p+1,p+n+1,cmpx); sort(t+1,t+tot+1); for(int i=1;i<=n;i++) p[i].z=lower_bound(t+1,t+tot+1,p[i].z)-t; CDQ(1,n); int ans=1; for(int i=1;i<=n;i++)ans=max(ans,p[i].ans); printf("%d\n",ans); return 0; } 相关文章推荐
- 微信获取openid
- JS日期,JS获取当前日期时间,js日期格式化
- C#-带有历史信息的菜单
- SparkML数据类型(DataTypes)之向量和数组
- BAT-使用BAT方法清理系统垃圾
- linux第七章笔记
- 微软2016校园招聘4月在线笔试 A FontSize
- wifi与wimax
- HDU 4005 The war 双连通分量 缩点
- UIWebView第三方进度条NJKWebViewProgress
- jvm参数设置 -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M
- 每天laravel-20160707|KeyWritten
- 干货技巧!有哪些实用秘诀可以帮助UI/UX设计师自我提升
- 视觉里程计总结
- 每天laravel-20160707|KeyWritten
- MongoDB3.0后的数据库安全认证
- 路径
- 闭包
- ECShop - 数据库操作类
- tinyint(4),tinyint(80)有什么区别