zoukankan      html  css  js  c++  java
  • bzoj2253纸箱堆叠(动态规划+cdq分治套树状数组)

    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 

    这题挺难的。

    下面是老师给我的题解:

        看这题有点像个3维的偏序问题,但并不完全是,题目要求的是最大的类似于套娃的东西。

        我们先按最短边排序,然后对于一个i,只有可能是j(1<=j<i)这个纸箱可以被i包含,我们记录f[i]表示i这个箱子可以包含多少个玩具。则很显然我们可以枚举这个j(1<=j<i)如果j被i完全包含,则f[i] = max(f[i], f[j] +1),最后在f数组中取最大值就是答案。

    这个DP是O(n^2)级别的,我们考虑怎么优化。

    方法一:

        考虑到我们在排序后未知的有2维,我们可以用树套树来实现,树套树代码短,简单无脑,但是速度非常慢,即使用最快的树状数组套线段树,最慢的点要跑到0.75ms。

    方法二:

        用分治来优化这个DP,还是先按x排序,然后对于一个区间L,R,记mid为区间中点,我们先递归处理(L,mid),然后考虑(L,mid)对(mid+1,r)的影响,因为我们已经保证x单调递增,然后我们保证前一段区间和后一段区间的y是单调递增的,然后我们就可以用1个指针w,并枚举i(mid+1<=i<=r),我们要保证w之前的y小于i之前的y,然后每次把w往后移,同时插入z坐标,对于枚举到的i,用一个数状数组查询之前的最大值。最后递归(mid+1, r)。

     

    我参考了dalao的博客。

    传送门:http://blog.csdn.net/v5zsq/article/details/51083312

      1 program box(input,output);
      2 var
      3   a,x,y,z,f,b,c,d:array[0..50050]of longint;
      4   h:array[0..1000000]of longint;
      5   m,p,n,i,j,t,l,r,mid,ans,cnt:longint;
      6   flag:boolean;
      7 function max(a,b:longint):longint;
      8 begin
      9    if a>b then exit(a) else exit(b);
     10 end;
     11 procedure sort0(q,h:longint);
     12 var
     13   i,j,c,t:longint;
     14 begin
     15    i:=q;j:=h;c:=x[(i+j)>>1];
     16    repeat
     17      while x[i]<c do inc(i);
     18      while c<x[j] do dec(j);
     19      if i<=j then
     20         begin
     21            t:=x[i];x[i]:=x[j];x[j]:=t;
     22            t:=y[i];y[i]:=y[j];y[j]:=t;
     23            t:=z[i];z[i]:=z[j];z[j]:=t;
     24            inc(i);dec(j);
     25         end;
     26    until i>j;
     27    if j>q then sort0(q,j);
     28    if i<h then sort0(i,h);
     29 end;
     30 procedure sorta(q,h:longint);
     31 var
     32   i,j,x,t:longint;
     33 begin
     34    i:=q;j:=h;x:=a[(i+j)>>1];
     35    repeat
     36      while a[i]<x do inc(i);
     37      while x<a[j] do dec(j);
     38      if i<=j then
     39         begin
     40            t:=a[i];a[i]:=a[j];a[j]:=t;
     41            inc(i);dec(j);
     42         end;
     43    until i>j;
     44    if j>q then sorta(q,j);
     45    if i<h then sorta(i,h);
     46 end;
     47 function find(x:longint):longint;
     48 begin
     49    l:=1;r:=m;
     50    while l<r-1 do
     51       begin
     52          mid:=(l+r)>>1;
     53          if a[mid]<x then l:=mid+1 else r:=mid;
     54       end;
     55    if a[l]=x then exit(l) else exit(r);
     56 end;
     57 procedure sort(q,h:longint);
     58 var
     59   i,j,x,t:longint;
     60 begin
     61    i:=q;j:=h;x:=b[(i+j)>>1];
     62    repeat
     63      while b[i]<x do inc(i);
     64      while x<b[j] do dec(j);
     65      if i<=j then
     66         begin
     67            t:=b[i];b[i]:=b[j];b[j]:=t;
     68            t:=c[i];c[i]:=c[j];c[j]:=t;
     69            t:=d[i];d[i]:=d[j];d[j]:=t;
     70            inc(i);dec(j);
     71         end;
     72    until i>j;
     73    if j>q then sort(q,j);
     74    if i<h then sort(i,h);
     75 end;
     76 procedure change(k,n:longint);
     77 begin
     78    while k<=m do
     79       begin
     80          if n>a[k] then begin a[k]:=n;inc(cnt);h[cnt]:=k; end else break;
     81          k:=k+k and (-k);
     82       end;
     83 end;
     84 function ask(k:longint):longint;
     85 var
     86   ans:longint;
     87 begin
     88    ans:=0;
     89    while k>0 do begin ans:=max(ans,a[k]);k:=k-k and (-k); end;
     90    exit(ans);
     91 end;
     92 procedure solve(l,r:longint);
     93 var
     94   mid:longint;
     95 begin
     96    if l=r then exit;
     97    flag:=false;
     98    for i:=l+1 to r do if x[i]<>x[i-1] then begin flag:=true;break; end;
     99    if not flag then exit;
    100    mid:=(l+r)>>1;
    101    i:=mid;j:=mid;if (r-l) mod 2=1 then inc(j);
    102    if x[i]<>x[j] then mid:=i
    103    else
    104       while true do
    105          begin
    106             dec(i);inc(j);
    107             if x[i]<>x[i+1] then begin mid:=i;break; end;
    108             if x[j]<>x[j-1] then begin mid:=j-1;break; end;
    109          end;
    110    solve(l,mid);
    111    for i:=l to r do begin b[i]:=y[i];c[i]:=z[i];d[i]:=i; end;
    112    sort(l,mid);sort(mid+1,r);
    113    i:=l;j:=mid+1;cnt:=0;
    114    while true do
    115       begin
    116          if j>r then break;
    117          if (i<=mid) and (b[i]<b[j]) then begin change(c[i],f[d[i]]);inc(i); end
    118          else begin f[d[j]]:=max(f[d[j]],ask(c[j]-1)+1);inc(j); end;
    119       end;
    120    for i:=1 to cnt do a[h[i]]:=0;
    121    solve(mid+1,r);
    122 end;
    123 begin
    124    assign(input,'box.in');assign(output,'box.out');reset(input);rewrite(output);
    125    readln(m,p,n);
    126    j:=1;
    127    for i:=1 to n do
    128       begin
    129          j:=j*m mod p;x[i]:=j;
    130          j:=j*m mod p;y[i]:=j;
    131          j:=j*m mod p;z[i]:=j;
    132          if x[i]>y[i] then begin t:=x[i];x[i]:=y[i];y[i]:=t; end;
    133          if x[i]>z[i] then begin t:=x[i];x[i]:=z[i];z[i]:=t; end;
    134          if y[i]>z[i] then begin t:=y[i];y[i]:=z[i];z[i]:=t; end;
    135       end;
    136    sort0(1,n);
    137    for i:=1 to n do a[i]:=z[i];
    138    sorta(1,n);
    139    m:=1;
    140    for i:=2 to n do if a[i]<>a[i-1] then begin inc(m);a[m]:=a[i]; end;
    141    for i:=1 to n do z[i]:=find(z[i]);
    142    for i:=1 to n do f[i]:=1;
    143    fillchar(a,sizeof(a),0);
    144    solve(1,n);
    145    ans:=0;
    146    for i:=1 to n do if f[i]>ans then ans:=f[i];
    147    write(ans);
    148    close(input);close(output);
    149 end.
  • 相关阅读:
    git 管理
    SVN 管理
    为什么要做静态库
    Sqlite3
    CocoaPod
    内存管理
    readline的用法
    join合并字符串时使用生成器表达式
    pandas DataFrame数据转为list
    Jenkins自动化CI CD流水线之4--Master-Slave架构
  • 原文地址:https://www.cnblogs.com/Currier/p/6557402.html
Copyright © 2011-2022 走看看