• [BZOJ]2253: [2010 Beijing wc]纸箱堆叠


    题解:   很明显的偏序关系  对于一个三元组[x,y,z]  你需要找到一个lis  满足 $$ x_1<x_2  y_1<y_2 z_1<z_2 $$ 对于一个组内的任意两个盒子都满足条件  首先对于普通的LIS我们可以用  $$ dp[x]=max(dp[x],dp[j]+1) left ( a[j]<=a[x] ight ) $$ 同理 我们知道偏序问题可以直接用CDQ去解  但这个CDQ和我们平时所维护的偏序关系不一样  我们需要在中序遍历的过程中维护出答案  即对于[l,r]区间  我们先把[l,mid]区间对[mid+1,r]dp做出来 然后[mid+1,r]内部更新即可

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=3e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    
    ll p,a;
    ll ycl[MAXN];
    typedef struct node{
        ll x,y,z;int id,pos;
        friend bool operator<(node aa,node bb){return aa.x<bb.x;}
    }node;
    node d[MAXN],ed[MAXN];int tot;
    vector<int>vec;
    int base,ans[MAXN];
    
    int maxx[MAXN<<2];
    
    void built(int rt,int l,int r,int t){
        maxx[rt]=0;
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(t<=mid)built(rt<<1,l,mid,t);
        else built(rt<<1|1,mid+1,r,t);
    }
    
    void update(int rt,int l,int r,int t,int k){
        maxx[rt]=max(maxx[rt],k);
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(t<=mid)update(rt<<1,l,mid,t,k);
        else update(rt<<1|1,mid+1,r,t,k);
    }
    
    int ans1;
    void query(int rt,int l,int r,int ql,int qr){
        if(ql>qr)return ;
        if(ql<=l&&r<=qr){ans1=max(ans1,maxx[rt]);return ;}
        int mid=(l+r)>>1;
        if(ql<=mid)query(rt<<1,l,mid,ql,qr);
        if(qr>mid)query(rt<<1|1,mid+1,r,ql,qr);
    }
    
    bool cmp1(node aa,node bb){return aa.y<bb.y;}
    bool cmp2(node aa,node bb){return aa.pos<bb.pos;}
    
    void merge(int l,int mid,int r){
        int i=l;int j=mid+1;
        for(int k=mid+1;k<=r;k++)d[k].pos=k;
        sort(d+mid+1,d+r+1,cmp1);
        tot=0;
        while(i<=mid&&j<=r){
    	while(i<=mid&&d[i].y<d[j].y){
    	    update(1,1,base,d[i].z,ans[d[i].id]);
    	    i++;
    	}
    	ans1=0;query(1,1,base,1,d[j].z-1);ans[d[j].id]=max(ans[d[j].id],ans1+1);
    	j++;
        }
        for(;j<=r;j++){
    	ans1=0;query(1,1,base,1,d[j].z-1);ans[d[j].id]=max(ans[d[j].id],ans1+1);
        }
        for(int i=l;i<=mid;i++)built(1,1,base,d[i].z);
        sort(d+mid+1,d+r+1,cmp2);
    }
    
    void cdq(int l,int r){
        if(l>=r)return ;
        int mid=(l+r)>>1;
        cdq(l,mid);
        merge(l,mid,r);
        cdq(mid+1,r);
        merge(l,mid,r);
        sort(d+l,d+r+1,cmp1);
    }
    
    int main(){
        a=read();p=read();int n=read();
        ycl[0]=1;
        inc(i,1,3*n)ycl[i]=ycl[i-1]*a%p;
        inc(i,1,n)ans[i]=1;
        inc(i,1,n){
    	d[i].id=i;
    	d[i].x=ycl[3*i-2],d[i].y=ycl[3*i-1],d[i].z=ycl[3*i];
    	if(d[i].x>d[i].z)swap(d[i].x,d[i].z);
    	if(d[i].y>d[i].z)swap(d[i].y,d[i].z);
    	if(d[i].x>d[i].y)swap(d[i].x,d[i].y);
    	vec.pb(d[i].z);vec.pb(d[i].z-1);
        }
        sort(vec.begin(),vec.end());
        base=unique(vec.begin(),vec.end())-vec.begin();
        inc(i,1,n)d[i].z=lower_bound(vec.begin(),vec.begin()+base,d[i].z)-vec.begin()+1;
        sort(d+1,d+n+1);
        cdq(1,n);
        int ans2=0;
        inc(i,1,n)ans2=max(ans2,ans[i]);
        printf("%d
    ",ans2);
    }
    

      

    2253: [2010 Beijing wc]纸箱堆叠

    Time Limit: 30 Sec  Memory Limit: 256 MB
    Submit: 677  Solved: 236
    [Submit][Status][Discuss]

    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
    【样例说明】
    生产出的纸箱的三边长为(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 mod p<>0,ap<=2000000000,1<=N<=50000
  • 相关阅读:
    flink源码阅读(概览)
    idea如何设置home目录
    博客园定制化从入门到精通
    CAP理论的理解
    几个常用的profiler工具对比jprofiler、vituralVM、yourkit、JVM profler
    kafka的使用经验
    netty高并发框架
    Mysql Explain 详解
    show engine innodb status解读
    Class.getResourceAsStream()与ClassLoader.getResourceAsStream()的区别
  • 原文地址:https://www.cnblogs.com/wang9897/p/10336564.html
Copyright © 2020-2023  润新知