bzoj 2253: [2010 Beijing wc]纸箱堆叠 (CDQ分治+DP)
2017-03-24 20:18
316 查看
题目描述
传送门
题目大意:每个物品有三个参数(x,y,z),一个物品只有三个参数同时严格小于另一个物品,才能放到另一个物品中。问最多多少个两两嵌套。题解
我们先按照x坐标排好序,然后进行CDQ分治。分治的时候先计算[l,mid]的中点的答案。
然后按照y排序,将原本[l,mid]中的点一次加入他们z值对应的树状数组中。
[r,mid]中的点从树状数组中查询小于z的区间最小值,更新答案。
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define N 50003 #define LL long long using namespace std; int f[N*3],n,base,p,tr[N*3],mul[N*3],b[N*3],cnt,ll[N*3],rr[N*3],c[N*3]; bool mark ; struct data{ int x,y,z,id,pd; }a ; int cmp(data a,data b) { return a.x<b.x; } int cmp1(data a,data b) { return a.y<b.y||a.y==b.y&&a.x<b.x; } int lowbit(int x){ return x&(-x); } void change(int x,int val) { for (int i=x;i<=cnt;i+=lowbit(i)) tr[i]=max(tr[i],val); } int query(int x) { int ans=0; if (!x) return 0; for (int i=x;i>=1;i-=lowbit(i)) ans=max(ans,tr[i]); return ans; } void clear(int x) { for (int i=x;i<=cnt;i+=lowbit(i)) tr[i]=0; } void divide(int l,int r) { if (l>=r) return; sort(a+l,a+r+1,cmp); //cout<<l<<" "<<r<<endl; //for (int i=l;i<=r;i++) cout<<a[i].x<<" "<<a[i].y<<" "<<a[i].z<<" "<<a[i].id<<endl; int mid=(l+r)/2; int L=ll[l]; int R=rr[r]; divide(l,mid); for (int i=L;i<=rr[mid];i++) a[i].pd=1; for (int i=rr[mid]+1;i<=R;i++) a[i].pd=0; sort(a+L,a+R+1,cmp1); int j; for (int i=L;i<=R;i=j+1) { j=i; while (j<R&&a[i].y==a[j+1].y) j++; for (int k=i;k<=j;k++) if (a[k].pd==0) { int t=a[k].id; f[t]=max(f[t],query(a[k].z-1)+1); } for (int k=i;k<=j;k++) if (a[k].pd==1) change(a[k].z,f[a[k].id]); } for (int i=L;i<=R;i++) if (a[i].pd==1) clear(a[i].z); sort(a+L,a+R+1,cmp); divide(mid+1,r); } int main() { freopen("a.in","r",stdin); freopen("my.out","w",stdout); scanf("%d%d%d",&base,&p,&n); mul[0]=1; int t=0; for (int i=1;i<=3*n;i++) mul[i]=(LL)mul[i-1]*base%p,b[i]=mul[i]; sort(b+1,b+3*n+1); cnt=unique(b+1,b+3*n+1)-b-1; for (int i=1;i<=n;i++){ int t1=(i-1)*3; a[i].id=i; //cout<<mul[t+1]<<" "<<mul[t+2]<<" "<<mul[t+3]<<endl; a[i].x=lower_bound(b+1,b+cnt+1,mul[t1+1])-b; a[i].y=lower_bound(b+1,b+cnt+1,mul[t1+2])-b; a[i].z=lower_bound(b+1,b+cnt+1,mul[t1+3])-b; if (a[i].y<a[i].x) swap(a[i].x,a[i].y); if (a[i].z<a[i].x) swap(a[i].x,a[i].z); if (a[i].z<a[i].y) swap(a[i].z,a[i].y); //cout<<a[i].x<<" "<<a[i].y<<" "<<a[i].z<<endl; c[++t]=a[i].x; } sort(c+1,c+t+1); t=unique(c+1,c+t+1)-c-1; // cout<<t<<endl; for (int i=1;i<=n;i++) a[i].x=lower_bound(c+1,c+t+1,a[i].x)-c; for (int i=1;i<=n;i++) f[i]=1; sort(a+1,a+n+1,cmp); a[n+1].x=1000000000; for (int i=1;i<=n;i++) { //cout<<a[i].x<<endl; if (a[i-1].x<a[i].x) ll[a[i].x]=i; if (a[i+1].x>a[i].x) rr[a[i].x]=i; } divide(1,t); int ans=0; for (int i=1;i<=n;i++) ans=max(ans,f[i]); printf("%d\n",ans); }
相关文章推荐
- BZOJ2253: [2010 Beijing wc]纸箱堆叠
- bzoj2253: [2010 Beijing wc]纸箱堆叠
- [BZOJ2253][2010 Beijing wc]纸箱堆叠(dp+bit+cdq分治)
- 【BZOJ】2253: [2010 Beijing wc]纸箱堆叠
- [BZOJ2253][2010 Beijing wc]纸箱堆叠(CDQ分治优化DP)
- BZOJ_2253_[2010 Beijing wc]纸箱堆叠 _CDQ分治+树状数组
- [BZOJ 2253][2010 Beijing wc]纸箱堆叠:CDQ分治|DP
- 【BZOJ2253】[2010 Beijing wc]纸箱堆叠 cdq分治
- bzoj2253 [2010 Beijing wc]纸箱堆叠(cdq分治+树状数组)
- 【BZOJ】【2253】【WC 2010 BeijingWC】纸箱堆叠
- [BZOJ2253][2010BJWC]纸箱堆叠(dp+cdq分治)
- 2253: [2010 Beijing wc]纸箱堆叠
- BZOJ2253 2010 Beijing wc 纸箱堆叠 CDQ分治
- BZOJ2253 [2010 Beijing wc]纸箱堆叠
- bzoj2253 [2010 Beijing wc]纸箱堆叠(CDQ+dp)
- BZOJ 2253 纸箱堆叠(CDQ分治)
- 【BZOJ2253】纸箱堆叠 [CDQ分治]
- 【BZOJ2253】纸箱堆叠
- 纸箱堆叠 BZOJ 2253
- BZOJ 2251 Beijing WC 2010 外星联络 后缀数组