JZOJ5060 公路建設

2021-07-30 14:46:28 字數 1579 閱讀 6043

乙個圖有

n 個點,

m條無向邊,其中第

i 條邊的權值是ci

。 有q 個詢問,每次給定乙個區間[l

i,ri

],請你計算出只選擇(編號在)這個區間內的邊,在使圖中連通塊數目盡量小的前提之下,選擇的邊的權值和的最小值。1≤

n≤102

,1≤m

≤105,

1≤q≤

1.5×104

顯然題目是求區間內的邊的最小生成森林的邊權和。

可以發現最小生成樹(森林)具有可合併性。

乙個很顯然的想法:將所有邊按照編號分塊,設每一塊大小為

b ,令fi

,j表示從第

i 個塊到第

j個塊的邊構成的最小生成森林的邊集,這個可以o(

n(mb

)2) 的時間複雜度完成。

然後詢問時直接拿出跨塊的

f 值以及兩邊多出來的邊合併一下就好了。 b取

m−−√

的話,時間複雜度可以做到o(

nm+q

(n+m

−−√)

(log(n

+m−−

√)+α

(n))

) (如果你實現得好一點,用歸併排序可以省掉

log )。

不過這個方法還是太*****了,我們把分塊換成線段樹就可以在o(

n(m+

q)logmα(

n)) 的時間複雜度內解決問題。

於是我依然特別*****地打了分塊。

#include 

#include

#include

#include

#include

using

namespace

std;

int read()

int buf[30];

void write(int x)

const

int n=105;

const

int m=100005;

const

int b=500;

int srt[m],id[m];

int fa[n],rank[n];

int mst[b][b][n];

int st[b],en[b];

int edg[m][3];

int n,m,q,cnt,bs,bcnt;

int getfather(int son)

void merge(int x,int y)

int kruscal(int *e)

return ret;

}void block()

for (int i=1;ifor (int j=i+1;j<=bcnt;++j)

}int main()

}if (lid) for (int i=1;i<=mst[lid][rid][0];++i) id[++cnt]=mst[lid][rid][i];

}fclose(stdin),fclose(stdout);

return

0;}

506 相對名次

給出 n 名運動員的成績,找出他們的相對名次並授予前三名對應的獎牌。前三名運動員將會被分別授予 金牌 銀牌 和 銅牌 gold medal silver medal bronze medal 注 分數越高的選手,排名越靠前。示例 1 輸入 5,4,3,2,1 輸出 gold medal silver...

506 相對名次(字典)

1.問題描述 給出 n 名運動員的成績,找出他們的相對名次並授予前三名對應的獎牌。前三名運動員將會被分別授予 金牌 銀牌 和 銅牌 gold medal silver medal bronze medal 注 分數越高的選手,排名越靠前。示例 1 輸入 5,4,3,2,1 輸出 gold medal...

Zjr506的捕貓計畫

zjr506很喜歡貓,某一天他突然心血來潮,想捕捉學校裡活動的貓。為了捕貓,zjr506在校園中放置了n個木樁,當他見到有貓進入他的狩獵範圍後,就會以迅雷不及掩耳的速度在一些木樁之間繞上藩籬以困住這些貓。一段時間後,zjr506在繞了m個藩籬後興高采烈的離開了。作為正義的使者,ztxz16不忍心看到...