洛谷 P2827 蚯蚓 解題報告
P2827 蚯蚓
題目描述
本題中,我們將用符號 \(\lfloor c \rfloor\) 表示對 \(c\) 向下取整,例如:\(\lfloor 3.0 \rfloor = \lfloor 3.1 \rfloor = \lfloor 3.9 \rfloor = 3\)。
蛐蛐國最近蚯蚓成災了!隔壁跳蚤國的跳蚤也拿蚯蚓們沒辦法,蛐蛐國王只好去請神刀手來幫他們消滅蚯蚓。
蛐蛐國裏現在共有 \(n\) 只蚯蚓(\(n\) 為正整數)。每只蚯蚓擁有長度,我們設第 \(i\) 只蚯蚓的長度為 \(a_i\)(\(i=1,2,\dots,n\)),並保證所有的長度都是非負整數(即:可能存在長度為 \(0\)
每一秒,神刀手會在所有的蚯蚓中,準確地找到最長的那一只(如有多個則任選一個)將其切成兩半。神刀手切開蚯蚓的位置由常數 \(p\)(是滿足 \(0 < p < 1\) 的有理數)決定,設這只蚯蚓長度為 \(x\),神刀手會將其切成兩只長度分別為 \(\lfloor px \rfloor\) 和 \(x - \lfloor px \rfloor\) 的蚯蚓。特殊地,如果這兩個數的其中一個等於 \(0\),則這個長度為 \(0\) 的蚯蚓也會被保留。此外,除了剛剛產生的兩只新蚯蚓,其余蚯蚓的長度都會增加 \(q\)(是一個非負整常數)。
蛐蛐國王知道這樣不是長久之計,因為蚯蚓不僅會越來越多,還會越來越長。蛐蛐國王決定求助於一位有著洪荒之力的神秘人物,但是救兵還需要 \(m\)
蛐蛐國王希望知道這 \(m\) 秒內的戰況。具體來說,他希望知道:
\(m\) 秒內,每一秒被切斷的蚯蚓被切斷前的長度(有 \(m\) 個數);
\(m\) 秒後,所有蚯蚓的長度(有 \(n + m\) 個數)。
蛐蛐國王當然知道怎麽做啦!但是他想考考你……
輸入輸出格式
輸入格式:
第一行包含六個整數 \(n,m,q,u,v,t\),其中:\(n,m,q\) 的意義見【問題描述】;\(u,v,t\) 均為正整數;你需要自己計算 \(p=u / v\)(保證 \(0 < u < v\));\(t\) 是輸出參數,其含義將會在【輸出格式】中解釋。
第二行包含 nn 個非負整數,為 \(a_1, a_2, \dots, a_n\),即初始時 \(n\) 只蚯蚓的長度。
同一行中相鄰的兩個數之間,恰好用一個空格隔開。
保證 \(1 \leq n \leq 10^5\),\(0 \leq m \leq 7 \times 10^6\),\(0 < u < v \leq 10^9\),\(0 \leq q \leq 200\),\(1 \leq t \leq 71\),\(0 \leq a_i \leq 10^8\)。
輸出格式:
第一行輸出 \(\left \lfloor \frac{m}{t} \right \rfloor\)個整數,按時間順序,依次輸出第 \(t\) 秒,第 \(2t\) 秒,第 \(3t\) 秒,……被切斷蚯蚓(在被切斷前)的長度。
第二行輸出 \(\left \lfloor \frac{n+m}{t} \right \rfloor\)個整數,輸出 \(m\) 秒後蚯蚓的長度;需要按從大到小的順序,依次輸出排名第 \(t\),第 \(2t\),第 \(3t\),……的長度。
同一行中相鄰的兩個數之間,恰好用一個空格隔開。即使某一行沒有任何數需要輸出,你也應輸出一個空行。
請閱讀樣例來更好地理解這個格式。
說明:
堆的做法很顯然,大概有65~80pts,算是送了很多分了
一看輸出都強行怕你T,那一定是\(O(n)\)了
記得合並果子有一個雙隊列\(O(n)\)做法嗎?
事實上跟這個題差不多噠
我們開三個隊列,一個存放原來的蚯蚓,一個存放被這樣切\(\lfloor px \rfloor\)的蚯蚓,另一個存放被\(x - \lfloor px \rfloorx\)這樣切的
註意到在後兩個隊列中先拿出來的一定比後拿出來的要長,具有單調性
對於第一個隊列我們可以先排序,然後每次取三個隊列中隊尾最大的,切開放到相應的隊頭
增加的量我們可以維護一個被切斷的時間點
註意中間過程可能會爆int
Code:
#include <cstdio>
#include <algorithm>
#define ll long long
const int N=8e6;
ll q1[N][2],q2[N][2],q3[N][2],l1=1,l2=1,l3=1,r1,r2,r3;
ll n,m,q,u,v,t,a[N];//n個m刀增q p=u/v t輸出
int main()
{
scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&q,&u,&v,&t);
for(int i=1;i<=n;++i)
scanf("%lld",a+i);
r1=n;
std::sort(a+1,a+1+n);
for(int i=1;i<=n;i++) q1[n+1-i][0]=a[i];
for(register ll mx,id,i=1;i<=m;++i)
{
mx=0;
if(l1<=r1&&mx<q1[l1][0]+(i-q1[l1][1]-1)*q) mx=q1[l1][0]+(i-q1[l1][1]-1)*q,id=1;
if(l2<=r2&&mx<q2[l2][0]+(i-q2[l2][1]-1)*q) mx=q2[l2][0]+(i-q2[l2][1]-1)*q,id=2;
if(l3<=r3&&mx<q3[l3][0]+(i-q3[l3][1]-1)*q) mx=q3[l3][0]+(i-q3[l3][1]-1)*q,id=3;
if(i%t==0) printf("%lld ",mx);
if(id==1) ++l1;if(id==2) ++l2;if(id==3) ++l3;
q2[++r2][0]=mx*u/v,q2[r2][1]=i;
q3[++r3][0]=mx-mx*u/v,q3[r3][1]=i;
}
printf("\n");ll i=0;
while(l1<=r1||l2<=r2||l3<=r3)
{
ll id,mx=0;++i;
if(l1<=r1&&mx<q1[l1][0]+(m-q1[l1][1])*q) mx=q1[l1][0]+(m-q1[l1][1])*q,id=1;
if(l2<=r2&&mx<q2[l2][0]+(m-q2[l2][1])*q) mx=q2[l2][0]+(m-q2[l2][1])*q,id=2;
if(l3<=r3&&mx<q3[l3][0]+(m-q3[l3][1])*q) mx=q3[l3][0]+(m-q3[l3][1])*q,id=3;
if(i%t==0) printf("%lld ",mx);
if(id==1) ++l1;if(id==2) ++l2;if(id==3) ++l3;
}
printf("\n");
return 0;
}
2018.9.1
洛谷 P2827 蚯蚓 解題報告