hdu6070 2017hdu多校第四場

2021-08-04 23:10:49 字數 1747 閱讀 4332

這道題是跟code force 834d很相像的一道題,題意說的是要求區間裡面不同數的個數除區間長度的最小值,首先先想到乙個公式si

ze(l

,r)r

−l+1

,size(l,r)指的是l到r區間裡有多少個不同的數。

我們可以列舉每個數,對於每個數來說,如果以這個數作為新的右端點,那麼左端點到上一次出現這個數之前的區間,都能享受到這個數作為乙個新的貢獻。也就是說這就是乙個對之前的dp區間的乙個區間更新,所以可以使用線段樹的區間更新操作來實現。按順序列舉過去就能得到下圖中的效果。橫線代表區間加1。

然後這樣操作過後,線段樹也是只能維護size的大小,題目要求的最值帶了除法,線段樹的區間lazy更新只能對滿足可加性的操作進行,對於乘除法可沒辦法。題目的核心是最小化乙個平均值。這個可以讓我們想到用二分來做。二分乙個答案mid ≥s

ize(

l,r)

r−l+

1 ,然後稍加變形,就能變成mi

d∗(r

+1)≥

size

(l,r

)+mi

d∗l 這樣就把除法給化掉了。size還是原來那個size,多了個r跟l,這個所幸也只是個陣列下標來的,只是在原來維護size的基礎上,再多加乙個單點更新,給線段樹裡面l位置加入乙個mid*l的值,然後區間查詢的時候,看能不能找到乙個si

ze(l

,r)r

−l+1

的最小值,讓那個等式成立了。

#include

using

namespace

std;

const

int maxn = 60000+10;

int n,k;

class seg//線段樹查詢區間最小值

}void pushup(int rt)

public:

void build(int rt,int l,int r)

int m=l+r>>1;

build(rt<<1,l,m);

build(rt<<1|1,m+1,r);

pushup(rt);

}void updata(int rt,int l,int r,int left,int right,double value)

pushdown(rt);

int m=l+r>>1;

if(left<=m) updata(rt<<1,l,m,left,right,value);

if(right>=m+1) updata(rt<<1|1,m+1,r,left,right,value);

pushup(rt);

}double query(int rt,int l,int r,int left,int right)

}seg;

int last[maxn];

int pos[maxn];

bool check(double mid)

return

false;

}int main()

int t;

cin>>t;

while(t--)

double l=0,r=1e9,mid;d

for(int i=0;i<50;i++)

printf("%.4f\n",mid);

}return

0;}

hdu多校題解

給定 n 求 sum limits sum mu d frac sum frac 再令 h n sum frac 則有 g n frac sum mu d frac h frac 推導 f 和 g 的關係 f n f sum limits frac sum limits g n g f n f 2 ...

hdu6579 2019hdu多校第一場1002

這題是cf 1100f原題,場上一堆人做出來了,然後我線段樹線性基時間也過不去,空間也過不去 看了題解後發現是個很容易的套路 我們對1.i的陣列維護乙個b i 的字首和線性基,但是線性基中的數字,我們每一位都要記錄乙個pos k 表示p k 是由第pos k 個數字填進去的,在插入的時候,我們讓k從...

HDU 5818 多校 7 模擬

題意 對棧的操作,有兩個棧 a b然後接下來n組操作包括入棧,出棧,合併棧。合併棧按入棧的時間順序進行排序。官方題解 比較簡單巧妙的乙個做法是引入乙個新的棧 c 每次合併的時候就把a和 b 合併到 c上,然後把 a 和 b都清空.pu sh還是按正常做,po p 注意當遇到要pop的棧為空時,因為題...