程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 紙箱堆疊 bzoj 2253,bzoj2253

紙箱堆疊 bzoj 2253,bzoj2253

編輯:C++入門知識

紙箱堆疊 bzoj 2253,bzoj2253


紙箱堆疊 (1s 128MB) box

【問題描述】

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個紙箱中數量最多的一個子集,使得它們兩兩之間都可嵌套堆疊起來。

【輸入格式】

輸入文件的第一行三個整數,分別代表 a, p, n

【輸出格式】

輸出文件僅包含一個整數,代表數量最多的可嵌套堆疊起來的紙箱的個數。

【樣例輸入】

 10 17 4

【樣例輸出】

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


題解:

主要算法:CDQ分治(快速排序,樹狀數組);動態規劃(Dp);

我們設長寬高為x,y,z

CDQ分治,以x為關鍵詞排序

接下來遞歸分成兩區間

假設左區間已經處理完了答案

將左右區間分別以y為關鍵字排序

那麼就保證了任何左區間的x必定小於任何右區間的x

我們用兩個指針分別從左右區間順序向後掃

將左區間的z作為位置不斷加入樹狀數組,值為當前點的答案

由於左右區間有序,可以手動保證右區間的掃到的點的y大於所有左區間掃到的點的y

就可以用樹狀數組更新右區間點的值:當前點的答案等於能轉移到當前點的點的答案加一的最大值,這裡用上了Dp的思想

然後清空樹狀數組,再將左右區間合並按第一維排序,恢復原狀態, 保證處理的是最初的右區間,且此區間按第一維有序

接著遞歸處理右區間,繼續更新答案

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 using namespace std;
  8 inline int Get()
  9 {
 10     int x = 0;
 11     char c = getchar();
 12     while('0' > c || c > '9') c = getchar();
 13     while('0' <= c && c <= '9')
 14     {
 15         x = (x << 3) + (x << 1) + c - '0';
 16         c = getchar();
 17     }
 18     return x;
 19 }
 20 const int me = 100233;
 21 struct box
 22 {
 23     int x, y, z, ans;
 24 };
 25 box c[me], s[me];
 26 int a, p, n, m;
 27 int tr[me];
 28 int num[me];
 29 inline bool rulex(box a, box b)
 30 {
 31     if(a.x != b.x) return a.x < b.x;
 32     if(a.y != b.y) return a.y < b.y;
 33     return a.z < b.z;
 34 }
 35 inline bool rules(int a, int b)
 36 {
 37     if(s[a].z != s[b].z) return s[a].z < s[b].z;
 38     if(s[a].x != s[b].x) return s[a].x < s[b].x;
 39     return s[a].y < s[b].y;
 40 }
 41 inline bool ruley(box a, box b)
 42 {
 43     if(a.y != b.y) return a.y < b.y;
 44     return a.z < b.z;
 45 }
 46 inline int Max(int x)
 47 {
 48     int maxx = 0;
 49     while(x > 0)
 50     {
 51         maxx = max(tr[x], maxx);
 52         x -= x & (-x);
 53     }
 54     return maxx;
 55 }
 56 inline void Ins(int x, int y)
 57 {
 58     while(x <= m)
 59     {
 60         tr[x] = max(tr[x], y);
 61         x += x & (-x);
 62     }
 63 }
 64 inline void Del(int x)
 65 {
 66     while(x <= m)
 67     {
 68         tr[x] = 0;
 69         x += x & (-x);
 70     }
 71 }
 72 inline int Maxx(int x, int y)
 73 {
 74     return (x > y) ? x : y;
 75 }
 76 void Work(int l, int r)
 77 {
 78     if(l == r) return;
 79     int mi = l + r >> 1;
 80     while(s[mi].x == s[mi - 1].x) --mi;
 81     if(mi < l) return;
 82     Work(l, mi);
 83     sort(s + l, s + mi + 1, ruley);
 84     sort(s + mi + 1, s + r + 1, ruley);
 85     int u = l, v = mi + 1;
 86     while(u <= mi && v <= r)
 87     {
 88         if(s[u].y < s[v].y)
 89         {
 90             Ins(s[u].z, s[u].ans);
 91             ++u;
 92         }
 93         else
 94         {
 95             s[v].ans = Maxx(s[v].ans, Max(s[v].z - 1) + 1);
 96             ++v;
 97         }
 98     }
 99     for(int i = v; i <= r; ++i)
100         s[i].ans = Maxx(s[i].ans, Max(s[i].z - 1) + 1);
101     for(int i = l; i <= mi; ++i) Del(s[i].z);
102     sort(s + mi + 1, s + r + 1, rulex);
103     Work(mi + 1, r);
104 }
105 int cc[4];
106 int main()
107 {
108     a = Get(), p = Get(), n = Get();
109     cc[0] = 1;
110     for(int i = 1; i <= n; ++i)
111     {
112         cc[1] = cc[0] * a % p;
113         cc[2] = cc[1] * a % p;
114         cc[3] = cc[2] * a % p;
115         cc[0] = cc[3];
116         sort(cc + 1, cc + 4);
117         c[i].x = cc[1], c[i].y = cc[2], c[i].z = cc[3];
118         c[i].ans = 1;
119     }
120     sort(c + 1, c + 1 + n, rulex);
121     for(int i = 1; i <= n; ++i)
122     {
123         if(c[i].x != c[i - 1].x || c[i].y != c[i - 1].y || c[i].z != c[i - 1].z)
124         {
125             s[++m] = c[i];
126             num[m] = m;
127         }
128     }
129     sort(num + 1, num + 1 + m, rules);
130     int k = 0;
131     for(int i = 1; i <= m; ++i)
132     {
133         k = i;
134         while(s[num[i]].z == s[num[i + 1]].z)
135         {
136             s[num[i]].z = k;
137             ++i;
138         }
139         s[num[i]].z = k;
140     }
141     Work(1, m);
142     int ans = 0;
143     for(int i = 1; i <= m; ++i)
144         if(s[i].ans > ans)
145             ans = s[i].ans;
146     printf("%d", ans);
147 }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved