• BZOJ2253 2010 Beijing wc 纸箱堆叠 CDQ分治


    这题之前度娘上没有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
    ",ans);
        return 0;
    }
    原文出处http://www.cnblogs.com/showson/
  • 相关阅读:
    洛谷 P1781 宇宙总统
    洛谷 P2524 Uim的情人节礼物·其之弐(康拓展开)
    洛谷 P1123 取数游戏
    洛谷 P4147 玉蟾宫 & P1169 [ZJOI2007]棋盘制作(求最大子矩阵)
    洛谷 P1387 最大正方形 & P2701 [USACO5.3]巨大的牛棚Big Barn (求最大子正方形)
    洛谷 P1464 Function
    洛谷 P1217 [USACO1.5]回文质数 Prime Palindromes
    洛谷 P1160 队列安排
    洛谷 P1451 求细胞数量
    洛谷 P1914 小书童——密码
  • 原文地址:https://www.cnblogs.com/showson/p/4277807.html
Copyright © 2020-2023  润新知