搬來的。。
題目大意
每一輪有若干個正整數,每一輪會選出最大的乙個(設其為 x)並將 x 用兩個數取代之,乙個是⌊x
∗p⌋ ,乙個是x−
⌊x∗p
⌋ ,
其中 p 為乙個取值範圍為(0,1)的實數,而其餘的數都會加上乙個非負整數 q。一開始有 n 個數,要進行 m 輪操作,問每輪操
作刪掉的數和最後剩下的數。
f1 ≤ n ≤ 10
5 , 1 ≤ m ≤ 7 × 10
6 解題思路
先來考慮這樣乙個東西:
假設當前輪的數中最大為 x,y 為其餘數中任意乙個。
顯然這一輪之後 x 會變成⌊x
∗p⌋ 和x−
⌊x∗p
⌋ ,設 y 會在 k 輪之後被選出來,那麼到時候 y 會變成⌊y
×p+k
×q×p
⌋ 和 y−
⌊y×p
+k×q
×p⌋
那麼在之後的第 k 輪裡,x 和 y 會變成⌊x × p⌋ + k × q,x + k × q − ⌊x × p⌋,⌊y × p + k × q × p⌋和 y − ⌊y × p + k × q × p⌋
考慮⌊x × p⌋ + k × q和⌊y × p + k × q × p⌋的大小關係:
將k × q放進下取整的式子裡得到:⌊x × p + k × q⌋
又因為x ≥ y,p ∈ (0,1)
所以⌊x × p + k × q⌋ > ⌊y × p + k × q × p⌋
類似的,可以得到:x + k × q − ⌊x × p⌋ > y − ⌊y × p + k × q × p⌋
那麼這個意味著什麼?
我們將每一輪的所有數分成三類:
1、最開始的數
2、是由某一輪的最大值 x 得到的⌊x × p⌋
3、是由某一輪的最大值 x 得到的x − ⌊x × p⌋
那麼開始的證明意味著第 2、3 種數中每次加入的數是不上公升的。
於是我們得到這樣乙個演算法:
對於每一種數我們維護乙個單調的佇列(三種就是說有 3 個佇列),一開始只有第 1 種數有 n 個數,從大到小排序放進佇列
裡。 每一輪在三個隊頭中取出最大的(由於佇列單調不上公升,這個數必然是當前所有數中最大的),設其為 x,然後將 x 分成兩個
數⌊x × p⌋,乙個是x − ⌊x × p⌋,設 a=⌊x × p⌋,b= x − ⌊x × p⌋,將 a 放到第二個佇列隊尾,b 放到第三個佇列隊尾並將 x 從其
自己的佇列中彈出。
對於每一輪其他數都加上 q 的操作可以通過記錄某個數第一次出現的時間,即假設當前為第 i 輪,x 為這個數最開始的值,t
為出現時間,那麼當前這個數為 x+(t-i)*q。
於是完美解決,空間複雜度 o(m)時間複雜度 o(m)
手打的 (被卡常了。。。改改陣列大小。。。)
#include
#include
#include
#include
#include
#include
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define n 7000005
#define inf 2147483647
using namespace std;
typedef double db;
int n,m,q,u,v,t;
int b[3],c[3],g[3][n], d[3][n];
inline int
read()
while(ch>='0'&&ch<='9')
return
x*w;
}bool cmp(int
x,int
y)int calc(int i,int
x)int pos(int
x)int main()
printf("\n");
fo(i,1,n+m)
return
0;}
NOIp2016提高組 蚯蚓
題目大意 給你n個不同長度蚯蚓,每秒從裡面取出最長的砍下u v變成兩隻,又把剩下的加長q。問你在m之前的t,2t,3t.的時間上,砍的蚯蚓長度,以及m秒後剩下所有的蚯蚓長度。思路 很容易想到用乙個堆來解決,然而這樣時間複雜度是o m n log m n 的,過不去。所以複雜度得是線性的。考慮把原來的...
NOIP2016提高組 蚯蚓
首先考慮暴力 每次都是拿最長的蚯蚓,容易想到用堆。每次除拿出來的以外所有的蚯蚓都增長,容易想到用乙個懶惰標記來記錄所有的蚯蚓增長了多少。取最大的元素出來後加上標記的值,放元素進去的時候減去標記的值。這時已經可以騙到60分了。假設某一次取出來的元素長度為x,當前標記的值為inc,切完以後放進去的就是 ...
Noip 2016 提高組第二試 蚯蚓
蛐蛐國裡現在共有n只蚯蚓 n為正整數 每只蚯蚓擁有長度,我們設第i只蚯蚓的長度為a i i 1,2,n 並保證所有的長度都是非負整數 即 可能存在長度為0的蚯蚓 每一秒,神刀手會在所有的蚯蚓中,準確地找到最長的那乙隻將其切成兩半。神刀手切開蚯蚓的位置由常數p決定,設這只蚯蚓長度為x,神刀手會將其切成...