ZJOI2010 基站選址

2022-05-25 12:36:12 字數 2177 閱讀 2019

洛谷題目鏈結

真毒瘤

這個題目耗了我半天。。結果是線段樹打錯了。。。

回歸正題:

線段樹$+dp$

首先當然是先考慮樸素$dp$啦,相信你既然都來做這題了,樸素的方程自然不用我多說,設$f[i][j]$表示在前$i$個村莊內,第$j$個基站建在$i$處的最小費用(不考慮$i$~$n$的賠償費用等)

方程為:

$$f[i][j]=min(f[k][j-1]+pay[k][i])$$

其中$pay[k][i]$表示從第$k$個村莊到第$i$個村莊的賠償費用之和

那麼我們觀察上面這個方程,這個方程是$o(n^2k)$的,可以發現類似於揹包問題,是可以滾掉一維,因為發現$f$陣列第二維只跟上次的值也就是$j-1$次的值有關,那麼我們只要直接利用上一次求出來的值繼續$dp$就行了,不需要多開一維,所以$dp$方程自然就化為$$f[i]=min(f[k]+pay[k][i])$$

那麼我們繼續思考:主要的時間消耗在了**?自然是怎麼快速計算$pay[k][i]$了

那麼我們思考:

對於每乙個村莊,都有乙個範圍內需要建立基站,否則就要賠償,那麼我們設第$i$個村莊的範圍為$[l,r]$,如果正在考慮$r$處建不建基站,那麼有下列情況:

$1$、不在$r$處設立基站,那麼對於村莊$i$來說,上乙個基站在$[1,l-1]$這個區間的話,就要賠償村莊$i$了,因為$[l,r]$這個區間沒有建基站,那麼我們就要快速的在$[1,l-1]$中區間加村莊$i$的賠償費用了,我們就以線段樹為例啦

$2$、在$r$處建立基站,那麼也就相當於最後乙個基站設立在$[1,r-1]$這個區間中,找乙個費用最小值來轉移嘛,還是線段樹$qwq$

所以我們要開乙個線段樹來維護$f+pay$的最小值,要有區間加法和區間查詢的操作

那麼為了上面的操作,我們還要開幾個陣列輔助(如果你是$dalao$當我沒說)

$st[i]$表示第$i$個村莊對應區間的左端點$l$

$ed[i]$表示第$i$個村莊對應區間的右端點$r$

那麼當$ed_x=i$的時候,如果$i$處不建,那麼就要區間加上$pay[x]$的值,然而可能有很多點的$ed$都是$i$,所以我們用鏈式前向星來儲存,具體可以看**實現

接下來就是美滋滋的**時間~~~

#include#include#include#include#define n 20007

#define int long long

#define inf 0x3f3f3f3f3f3f3f3f

using namespace std;

struct edge

edge[n<<2];

struct tree

tr[n<<2];

int n,k,cnt;

int dis[n],val[n],range[n],pay[n],st[n],ed[n],head[n],f[n];

void add(int u,int v)

; head[u]=cnt;

}void get()

}void pushup(int rt)

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

int mid=l+((r-l)>>1);

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

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

pushup(rt);

}void pushdown(int rt)

}int search(int rt,int l,int r,int l,int r)

pushdown(rt);

int mid=l+((r-l)>>1);

if(l<=mid)

update(rt<<1,l,mid,l,r,c);

if(midupdate(rt<<1|1,mid+1,r,l,r,c);

pushup(rt);

}void dp()

} int ans=f[n];

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

// for(int i=2;i<=k;++i)

}ans=min(ans,f[n]);//cout<<"ans:"<} printf("%lld",ans);

}void init()

signed main()

ZJOI2010 基站選址 線段樹優化dp難題

個人覺得這道題很難.最近我要總結幾篇 dp系列 了。令dp i j 表示,在第i個位置建造第j個基站時的最小代價。為了方便,我們令n n 1,k k 1。給最後乙個點的c賦0,d和w都賦inf 0x3f3f3f3f,如果用0x7fffffff會爆int 這樣的好處是最後乙個站一定建造 否則inf就變...

bzoj 1835 ZJOI2010 基站選址

有n個村莊坐落在一條直線上,第i i 1 個村莊距離第1個村莊的距離為di。需要在這些村莊中建立不超過k個通訊基站,在第i個村莊建立基站的費用為ci。如果在距離第i個村莊不超過si的範圍內建立了乙個通訊基站,那麼就成它被覆蓋了。如果第i個村莊沒有被覆蓋,則需要向他們補償,費用為wi。現在的問題是,選...

P2605 ZJOI2010 基站選址

有n個村莊坐落在一條直線上,第i i 1 個村莊距離第1個村莊的距離為di。需要在這些村莊中建立不超過k個通訊基站,在第i個村莊建立基站的費用為ci。如果在距離第i個村莊不超過si的範圍內建立了乙個通訊基站,那麼就村莊被基站覆蓋了。如果第i個村莊沒有被覆蓋,則需要向他們補償,費用為wi。現在的問題是...