設f[i][j]表示在第i個村莊建第j個基站的花費
那麼有$f[i][j]=min\$,其中w[k,i]表示在k,i建基站,k,i中間的不能被滿足的村莊的賠償金之和
如果把每個村莊能被滿足的區間處理出來,記做$[l_i,r_i]$,那麼i,j不能滿足的村莊,就是$i考慮將$f[i][k]+w[i,j]$的i固定,而j隨著dp進行而變化,這樣維護k個線段樹
那麼當j越來越大,會有更多的村莊[l,r]變得滿足r用堆來維護這些村莊,按r從大到小排序即可
複雜度$o(nklogn)$
1 #include2#define pa pair3
#define clr(a,x) memset(a,x,sizeof(a))
4#define mp make_pair
5using
namespace
std;
6 typedef long
long
ll;7
const
int maxn=2e4+10,maxk=105;8
9 inline char
gc()
14inline ll rd()
17while(c>='
0'&&c<='
9') x=(x<<1)+(x<<3)+c-'
0',c=gc();
18return neg?(~x+1
):x;19}
2021
intn,k,f[maxn][maxk],pos[maxn],cost[maxn];
22struct
nodep[maxn];
25int mi[maxk*maxn*2],laz[maxk*maxn*2],ch[maxk*maxn*2][2
],rt[maxk],pct;
26 inline bool
operator
< (node a,node b)
27 priority_queueq;
2829 inline void tag(int p,int
v)32
33 inline void pushdown(int
p)40 inline void update(int
p)43
44 inline void add(int p,int l,int r,int x,int y,int
z)52}53
54 inline int query(int p,int l,int r,int x,int
y)61
62 inline void change(int p,int l,int r,int x,int
y)70}71
72 inline void build(int &p,int l,int
r)78}79
80int
main()
94for(i=1;i<=n;i++)
95 p[i].w=rd();
96 p[n+1].l=n+1,p[n+1].r=n+1,p[n+1].w=233333333,n++,k++;
97 clr(f,127);f[0][0]=0;98
for(i=1;i<=k;i++) build(rt[i],1
,n);
99for(i=1;i<=n;i++)
107 f[i][1]=f[0][0]+cost[i];change(rt[1],1,n,i,f[i][1
]);108
for(k=2;k<=min(i,k);k++)
112q.push(p[i]);
113}
114int ans=2e9;
115for(i=1;i<=k;i++) ans=min(ans,f[n][i]);
116 printf("
%d\n
",ans);
117return0;
118 }
題解 lg2605 基站選址
題面 設 f i,j 表示前 i 個村莊建立 j 個基站,且第 i 個村莊有基站的最小花費 則有 f i,j min 其中 cost k,i 表示第 i k 個村莊建有基站,中間沒有,所需要補償的費用 發現轉移式中從 j 1 j 我們可以脫去 j 這一維 考慮怎麼計算 cost k,i k i 如果...
P2605 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。現在的問題是...