bzoj2253 [2010 Beijing wc]纸箱堆叠(CDQ+dp)
2017-12-18 17:13
411 查看
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,nOutput
输出文件仅包含一个整数,代表数量最多的可嵌套堆叠起来的纸箱的个数。Sample Input
10 17 4Sample Output
2【样例说明】
生产出的纸箱的三边长为(10, 15, 14), (4, 6, 9) , (5, 16, 7), (2, 3, 13)。其中只有
(4, 6, 9)可堆叠进(5, 16, 7),故答案为 2。
2<=P<=2000000000,1<=a<=p-1,a^k modp<>0,ap<=2000000000,1<=N<=50000
[Submit][Status][Discuss]
分析:
这道题第一眼就是dp
状态:f[i]表示以第i个盒子为最大盒,能装的最多盒子
转移方程:f[i]=max(f[j]+1) (j盒能装进i中)
现在的问题就是针对每一个i,寻找符合条件j
一看这个形式:三维偏序CDQ!?
但是这个p的范围是2*1e9,直接开树状数组就是找死
那怎么办呢?离散化啊!
但是CDQ只能计算出针对第i个盒子,有多少个盒子能够放在ta里面,但是我们需要找到具体是哪个啊,怎么办
仔细观察一下转移方程:
f[i]=max(f[j]+1)
实际上我们只关心最大值而我们的树状数组是可以维护最大值的!
这样我们的解题思路就出来了:
计算出每一个盒子的尺寸(注意三维的数据要排好序)
把所有数据离散化
CDQ分治(树状数组维护前驱最大值)、
我好不容易把做法想全huo了,然而写出来就是WA
看了一下题解,发现有几个蛮难受的点
离散化(这样比较优美)
sort(tmp+1,tmp+1+n*3); for (int i=1;i<=n;i++) po[i].a=lower_bound(tmp+1,tmp+1+n*3,po[i].a)-tmp; for (int i=1;i<=n;i++) po[i].b=lower_bound(tmp+1,tmp+1+n*3,po[i].b)-tmp; for (int i=1;i<=n;i++) po[i].c=lower_bound(tmp+1,tmp+1+n*3,po[i].c)-tmp;
变量x
(具体作用没有搞明白,大概是为了防止WA)
int M=(L+R)>>1,x=1e9; for (int i=L;i<R;i++) if (po[i].a!=po[i+1].a && abs(i-M)<abs(x-M)) x=i; if (x==1e9) return; M=x;
CDQ的顺序
这道题目和以前做的CDQ分治不一样,
这道题前面的信息对后面是有影响的
也就是说,只有[L,M]对[M+1,R]的影响处理完了,才能做[M+1,R]的
这样的话处理顺序是先[L,M],再处理区间之间的影响,最后[M+1,R]
CDQ(L,M); sort(po+L,po+M+1,cmp); //按b排序 sort(po+M+1,po+R+1,cmp); ... sort(po+M+1,po+R+1,cmp0); //一定要恢复之前的状态(按a排序),再分治右区间 CDQ(M+1,R);
tip
mdzz,这道题磨了一下午。。。//这里写代码片
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=50010;
struct node{
int a,b,c,ans;
};
node po
,q
;
int t[N<<2],n,p,a,tmp[N<<2];
void clear(int x) {for (int i=x;i<=n*3;i+=(i&(-i))) t[i]=0;}
void add(int x,int z) {for (int i=x;i<=n*3;i+=(i&(-i))) t[i]=max(t[i],z);}
int ask(int x) {int ans=0;for (int i=x;i>0;i-=(i&(-i))) ans=max(ans,t[i]);return ans;}
int cmp0(const node &A,const node &B)
{
if (A.a!=B.a) return A.a<B.a;
else if (A.b!=B.b) return A.b<B.b;
else return A.c<B.c;
}
int cmp(const node &A,const node &B)
{
if (A.b!=B.b) return A.b<B.b;
else return A.c<B.c;
}
void CDQ(int L,int R)
{
if (L==R) return;
int M=(L+R)>>1,x=1e9; for (int i=L;i<R;i++) if (po[i].a!=po[i+1].a && abs(i-M)<abs(x-M)) x=i; if (x==1e9) return; M=x;
CDQ(L,M);
sort(po+L,po+M+1,cmp); //按b排序
sort(po+M+1,po+R+1,cmp);
int t1=L,t2=M+1;
while (t2<=R)
{
if ((t1<=M&&po[t1].b<po[t2].b)||t2>R) //严格小于
add(po[t1].c,po[t1].ans),t1++;
else
po[t2].ans=max(po[t2].ans,ask(po[t2].c-1)+1),t2++; //严格小于
}
for (int i=L;i<t1;i++)
clear(po[i].c);
sort(po+M+1,po+R+1,cmp0); //一定要恢复之前的状态(按a排序),再分治右区间
CDQ(M+1,R);
}
int main()
{
scanf("%d%d%d",&a,&p,&n);
int num=a%p;
for (int i=1;i<=n;i++)
{
po[i].ans=1;
po[i].a=num%p; tmp[i]=num%p; num=num*a%p;
po[i].b=num%p; tmp[i+n]=num%p; num=num*a%p;
po[i].c=num%p; tmp[i+n*2]=num%p; num=num*a%p;
if (po[i].a<po[i].b) swap(po[i].a,po[i].b);
if (po[i].b<po[i].c) swap(po[i].b,po[i].c);
if (po[i].a<po[i].b) swap(po[i].a,po[i].b);
}
//离散化
sort(tmp+1,tmp+1+n*3); for (int i=1;i<=n;i++) po[i].a=lower_bound(tmp+1,tmp+1+n*3,po[i].a)-tmp; for (int i=1;i<=n;i++) po[i].b=lower_bound(tmp+1,tmp+1+n*3,po[i].b)-tmp; for (int i=1;i<=n;i++) po[i].c=lower_bound(tmp+1,tmp+1+n*3,po[i].c)-tmp;
sort(po+1,po+1+n,cmp0); //按照a排序
CDQ(1,n);
int Ans=-1;
for (int i=1;i<=n;i++) Ans=max(Ans,po[i].ans);
printf("%d",Ans);
return 0;
}
相关文章推荐
- BZOJ2253 2010 Beijing wc 纸箱堆叠 CDQ分治
- [BZOJ 2253][2010 Beijing wc]纸箱堆叠:CDQ分治|DP
- [BZOJ2253][2010 Beijing wc]纸箱堆叠(CDQ分治优化DP)
- BZOJ2253 [2010 Beijing wc]纸箱堆叠
- 【BZOJ2253】[2010 Beijing wc]纸箱堆叠 cdq分治
- bzoj2253 [2010 Beijing wc]纸箱堆叠(cdq分治+树状数组)
- bzoj 2253: [2010 Beijing wc]纸箱堆叠 (CDQ分治+DP)
- BZOJ_2253_[2010 Beijing wc]纸箱堆叠 _CDQ分治+树状数组
- 【BZOJ】2253: [2010 Beijing wc]纸箱堆叠
- bzoj2253: [2010 Beijing wc]纸箱堆叠
- 2253: [2010 Beijing wc]纸箱堆叠
- BZOJ2253: [2010 Beijing wc]纸箱堆叠
- [BZOJ2253][2010 Beijing wc]纸箱堆叠(dp+bit+cdq分治)
- 【BZOJ2253】纸箱堆叠 [CDQ分治]
- bjoi 2010 纸箱堆叠 二维树状数组
- BZOJ 2253 纸箱堆叠(CDQ分治)
- 【BZOJ】【2253】【WC 2010 BeijingWC】纸箱堆叠
- [BZOJ2253][2010BJWC]纸箱堆叠(dp+cdq分治)
- 【DP】【Asia - Harbin - 2010/2011】【Permutation Counting】
- BZOJ2001 [Hnoi2010]City 城市建设 CDQ分治