zoukankan      html  css  js  c++  java
  • 【BZOJ2253】纸箱堆叠 [CDQ分治]

    纸箱堆叠

    Time Limit: 30 Sec  Memory Limit: 256 MB
    [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。

    HINT

      2<=P<=2000000000,  1<=a<=p-1, a^k mod p<>0, ap<=2000000000, 1<=N<=50000

    Main idea

      每一个元素有三个属性a,b,c,求出最大可连续堆叠个数(可堆叠条件是a1<a2,b1<b2,c1<c2)

    Solution

      题目显然是三维偏序问题,运用CDQ分治求解。

      用排序处理a保证a有序,分治的时候满足左区间的b都小于右区间的b,再处理c,这样问题就转化为了求一个点在一个平面上横纵坐标都小于它的点有几个,用树状数组处理即可。

      发现这样处理之后答案只能满足<=该点,考虑如何令答案严格小于

      首先b,c的严格小于处理显然,因为a是sort保证的那么如何要使得a的统计严格小于呢?只需要在b的sort前将分割的指针向左移动到第一个不等于的即可,结合分治考虑一下while(q[mid].a==q[mid-1].a) mid--,发现这样处理最后会影响到排序,所以做右区间的时候重新按照a排序一下即可。

      考虑如何统计答案,发现显然有: q[j].ans=max(q[j].ans,Query(q[j].c-1)+1)

    Code

      1 #include<iostream>  
      2 #include<string>  
      3 #include<algorithm>  
      4 #include<cstdio>  
      5 #include<cstring>  
      6 #include<cstdlib>  
      7 #include<cmath>  
      8 using namespace std;  
      9    
     10 const int ONE=1000001;
     11  
     12 int n,MOD,a,m;
     13 int PD[4];
     14 int res;
     15 int C[ONE];
     16 int Ans,cnt;
     17  
     18 struct power
     19 {
     20         int a,b,c;
     21         int ans;
     22 }q[ONE];
     23  
     24 struct point
     25 {
     26         int pos,value;
     27 }Lisa[ONE];
     28  
     29 int get() 
     30 { 
     31         int res,Q=1;    char c;
     32         while( (c=getchar())<48 || c>57)
     33         if(c=='-')Q=-1;
     34         if(Q) res=c-48; 
     35         while((c=getchar())>=48 && c<=57) 
     36         res=res*10+c-48; 
     37         return res*Q; 
     38 }
     39  
     40 int cmp(const power &a,const power &b)
     41 {
     42         if(a.a!=b.a) return a.a<b.a;
     43         if(a.b!=b.b) return a.b<b.b;
     44         return a.c<b.c;
     45 }
     46  
     47 int cdp(const power &a,const power &b)
     48 {
     49         if(a.b!=b.b) return a.b<b.b;
     50         return a.c<b.c;
     51 }
     52  
     53 int rule(const power &a,const power &b)
     54 {
     55         return (a.a==b.a && a.b==b.b && a.c==b.c);
     56 }
     57  
     58 int lowbit(int x)
     59 {
     60         return x&-x;
     61 }
     62   
     63 int Add(int R,int x)
     64 {
     65         for(int i=R;i<=cnt;i+=lowbit(i))
     66         C[i]=max(C[i],x);
     67 }
     68   
     69 int Query(int R)
     70 {
     71         res=0;
     72         for(int i=R;i>=1;i-=lowbit(i))
     73         res=max(res,C[i]);
     74         return res;
     75 }
     76  
     77 int Clear(int R)
     78 {
     79         for(int i=R;i<=cnt;i+=lowbit(i))
     80         C[i]=0;
     81 }
     82  
     83 int clis(const point &a,const point &b)
     84 {
     85         return a.value<b.value;
     86 }
     87  
     88 void GetLisan()
     89 {
     90         sort(q+1,q+n+1,cmp);
     91         n=unique(q+1,q+n+1,rule)-1-q;
     92          
     93         for(int i=1;i<=n;i++)
     94         {
     95             Lisa[i].pos=i;
     96             Lisa[i].value=q[i].c;           
     97         }
     98         sort(Lisa+1,Lisa+n+1,clis);
     99          
    100         cnt=0;
    101         Lisa[0].value=-1;
    102         for(int i=1;i<=n;i++)
    103         {
    104             if(Lisa[i].value!=Lisa[i-1].value) cnt++;
    105             q[Lisa[i].pos].c=cnt;
    106         }
    107          
    108 }
    109  
    110 void Deal(int l,int r)
    111 {
    112         if(l>=r) return;
    113         int mid=(l+r)/2;
    114         while(q[mid].a==q[mid-1].a) mid--;
    115         if(mid<l) return;
    116         Deal(l,mid);   
    117         sort(q+l,q+mid+1,cdp);  sort(q+mid+1,q+r+1,cdp);
    118          
    119         int i=l,j=mid+1;
    120         while(j<=r)
    121         {
    122             while(i<=mid && q[i].b<q[j].b)
    123             {
    124                 Add(q[i].c,q[i].ans);
    125                 i++;    
    126             }
    127               
    128             q[j].ans=max(q[j].ans,Query(q[j].c-1)+1);
    129             j++;
    130         }
    131          
    132   
    133         for(int T=l;T<=mid;T++) 
    134         { 
    135             Clear(q[T].c);  
    136         }
    137         sort(q+mid+1,q+r+1,cmp);
    138         Deal(mid+1,r);
    139 }
    140  
    141 int main()
    142 {      
    143         a=get();    MOD=get();  n=get();
    144         int j=0;    res=1;
    145         for(int i=1;i<=n;i++)
    146         {
    147             for(int j=1;j<=3;j++)
    148             {
    149                 res=(long long)res*a%MOD;
    150                 PD[j]=res;
    151             }
    152             sort(PD+1,PD+3+1);
    153             q[i].a=PD[1]; q[i].b=PD[2]; q[i].c=PD[3];
    154             q[i].ans=1;
    155         }
    156          
    157         GetLisan();
    158          
    159         Deal(1,n);
    160         for(int i=1;i<=n;i++)
    161         Ans=max(Ans,q[i].ans);
    162          
    163         printf("%d",Ans);
    164 }
    View Code
  • 相关阅读:
    树莓派4B 多屏 QT程序窗口全屏 QScreen 只能获取1个屏幕
    树莓派4B 微雪7寸触摸屏 双屏 触摸屏校正
    虚拟机 ubuntu18 树莓派4 QT5.14.2 交叉编译
    Qt 指定 so库 运行时路径
    building qtqml requires python
    python django 测试报告 发送邮件
    jmeter XPath Extractor
    python+unittest+HTMLTestRunner生成测试报告
    Genymotion、 uiautomatorviewer、 appium报错
    jmeter forEach控制器
  • 原文地址:https://www.cnblogs.com/BearChild/p/6426669.html
Copyright © 2011-2022 走看看