您的位置:首页 > 其它

BZOJ2253 2010 Beijing wc 纸箱堆叠 CDQ分治

2015-02-06 18:41 323 查看
这题之前度娘上没有CDQ分治做法,gerwYY出来以后写了一个。不过要sort3遍,常数很大。

gerw说可以类似划分树的思想优化复杂度,但是蒟蒻目前不会划分树(会了主席树就懒得去弄了)。

嗯 将memset改成手动clear会快很多。

还有就是第一维相同的情况,划分为两个不存在第一维相同的两个区间即可。

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int Maxn=100000 + 10;
int C[Maxn*2],ans=0,A,P,n=0,h[Maxn],tot=0;
struct Node{
int a,b,c,ans;
void init(int x,int y,int z){
if(x>y)swap(x,y);
if(x>z)swap(x,z);
if(y>z)swap(y,z);
a=x,b=y,h[++tot]=c=z;
ans=1;
}
}p[Maxn],q[Maxn];
inline void Add(int x,const int&y){
for(;0<x&&x<=n;x+=x&-x)C[x]=max(C[x],y);
}
inline void HashIt(int&x){
x=lower_bound(h+1,h+n+1,x)-h;
}
inline int Query(int x){
int ret=0;
for(;0<x&&x<=n;x-=x&-x)ret=max(ret,C[x]);
return ret;
}
inline void Clear(int x) {
for(;x<=n;x+=x&-x)C[x]=0;
}
inline bool cmpa(const Node&x,const Node&y){
if(x.a!=y.a)return x.a<y.a;
if(x.b!=y.b)return x.b<y.b;
return x.c<y.c;
}
inline bool cmpb(const Node&x,const Node&y){
if(x.b!=y.b)return x.b<y.b;
return x.c<y.c;
}
void init(){
scanf("%d%d%d",&A,&P,&n);
for(int a,b,c,t=1,i=1;i<=n;i++){
a=(t=(long long)A*t%P);
b=(t=(long long)A*t%P);
c=(t=(long long)A*t%P);
p[i].init(a,b,c);
}
sort(p+1,p+n+1,cmpa);
sort(h+1,h+n+1);
for(int i=1;i<=n;i++)HashIt(p[i].c);
}

void CDQ(int l,int r){
if(l==r)return;
int mid=-1,L=(l+r)>>1,R=L+1;
while(l<=L || R<=r){
if(l<=L && p[L].a!=p[L+1].a){mid=L;break;}
if(R<=r && p[R].a!=p[R-1].a){mid=R-1;break;}
L--,R++;
}
if(mid==-1)return;
CDQ(l,mid);
sort(p+l,p+mid+1,cmpb);
sort(p+mid+1,p+r+1,cmpb);
int i=l;
for(int j=mid+1;j<=r;j++){
for(;i<=mid && p[i].b<p[j].b;i++)Add(p[i].c,p[i].ans);
p[j].ans=max(p[j].ans,Query(p[j].c-1)+1);
}
for(int j=l;j<=i;j++)Clear(p[j].c);
sort(p+mid+1,p+r+1,cmpa);
CDQ(mid+1,r);
}
int main(){
init();
CDQ(1,n);
for(int i=1;i<=n;i++)
if(p[i].ans>ans)ans=p[i].ans;
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: