BZOJ2253 紙箱堆疊 CDQ分治

2022-05-20 07:38:18 字數 3110 閱讀 3051

time limit: 30 sec  memory limit: 256 mb

[submit][status][discuss]

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

每乙個元素有三個屬性a,b,c,求出最大可連續堆疊個數(可堆疊條件是a1

題目顯然是三維偏序問題,運用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)

1 #include2 #include  

3 #include4 #include5 #include6 #include7 #include8

using

namespace

std; 910

const

int one=1000001;11

12int

n,mod,a,m;

13int pd[4

];14

intres;

15int

c[one];

16int

ans,cnt;

1718

struct

power

19q[one];

2324

struct

point

25lisa[one];

2829

intget

() 30

3940

int cmp(const power &a,const power &b)

4146

47int cdp(const power &a,const power &b)

4852

53int rule(const power &a,const power &b)

5457

58int lowbit(int

x)59

6263

int add(int r,int

x)64

6869

int query(int

r)70

7677

int clear(int

r)78

8283

int clis(const point &a,const point &b)

8487

88void

getlisan()

8998 sort(lisa+1,lisa+n+1

,clis);

99100 cnt=0

;101 lisa[0].value=-1

;102

for(int i=1;i<=n;i++)

103107

108}

109110

void deal(int l,int

r)111

127128 q[j].ans=max(q[j].ans,query(q[j].c-1)+1

);129 j++;

130}

131132

133for(int t=l;t<=mid;t++)

134137 sort(q+mid+1,q+r+1

,cmp);

138 deal(mid+1

,r);

139}

140141

intmain()

142152 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

157getlisan();

158159 deal(1

,n);

160for(int i=1;i<=n;i++)

161 ans=max(ans,q[i].ans);

162163 printf("%d"

,ans);

164 }

view code

bzoj2253 紙箱堆疊

題目鏈結 求三元組的嚴格上公升子串行 先考慮暴力 dp 一下 for int i 1 i n i for int j 1 j i j if x i x j y i y j z i z j f i max f i f j 1 考慮用 cdq 分治優化這個 dp 大體思路是,先按照第一維排序,保證第一維...

BZOJ 2253 紙箱堆疊(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 ...

2253 Frogger 解題報告

accecpttime 2008 12 30 11 11 23 language c memory 572k time 16ms errors 2wa algorithm dijkstra最短路徑 include include include include include using names...