一條線上有n個點,每個點都有乙個權值,每個點都可以選擇放置乙個監測器,假設i點有監測器,那麼假設i點左邊最靠近i點的監測器在j點,那麼i點的監測器就可以監測j+1到i的所有點
每個點放置監測器都有花費(這個花費不是點的權值),而且假設在y點放置了監測器,並且y點的監測器監測了x到y的所有點,那麼除了放置監測器的花費之外,還需要將x到y-1裡的點消耗額外的花費:設k點在x到y-1的點中,那麼k點會消耗y點與k點之間的點數(不算k點,但是算y點)乘上k的權值
要求能監測到n個點(也意味著第n個點必須要放監測器)的最小費用
dp,資料範圍太大只能dp
f[i]表示在第i個位置放置監測器的最小費用,顯然直接dp會t
那麼就斜率優化
f[i]=min(f[j]+a[i]+(i-(j+1))*b[j+1]+(i-(j+2))*b[j+2]...)
其實可以發現
f[i]=min(f[j]+a[i]+i*b[j+1]-(j+1)*b[j+1]+i*b[j+2]-(j+2)*b[j+2]...)
f[i]=min(f[j]+a[i]+i*(b[j+1]+b[j+2]+...)-(j+1)*b[j+1]-(j+2)*b[j+2]...)
設sb[i]=b[1]+b[2]+...+b[i]
cb[i]=b[1]*1+b[2]*2+b[3]*3...+b[i]*i
然後就得到f[i]=min(f[j]+a[i]+i*(sb[i-1]-sb[j])-(cb[i-1]-cb[j]))
接著化簡斜率方程,設j1
(f[j2]-f[j1]+cb[j2]-cb[j1])/(sb[j2]-sb[j1])
然後a了,要加long long
#include#include#include
#include
#include
using
namespace
std;
typedef
long
long
ll;ll f[
1100000
];ll a[
1100000],b[1100000
];ll sb[
1100000],cb[1100000
];//
f[i]=min(f[j]+a[i]+i*(sb[i-1]-sb[j])-(cb[i-1]-cb[j]))
double slop(int j1,int j2)//
(f[j2]-f[j1]+cb[j2]-cb[j1])/(sb[j2]-sb[j1])
int list[1100000
];int
main()
int head=1,tail=1;list[1]=0
;
for(int i=1;i<=n;i++)
printf(
"%lld\n
",f[n]);
return0;
}
bzoj 3437 小P的牧場
方程不難寫出fi max j 0 i 其中w j i 表示前 i 個牧場中,在 i處建立最後乙個檢查站,在 j 處建立倒數第二個檢查站的最小化費 這裡的w可以用兩個字首和求出,s1 i b i s2 i 1 a i 1 2 a i 2 3 a i 3 i 1 a 1 那麼w l,r s2 r s 2...
bzoj3437 小P的牧場
description 小p在mc裡有n個牧場,自西向東呈一字形排列 自西向東用1 n編號 於是他就煩惱了 為了控制這n個牧場,他需要在某些牧場上面建立控制站,每個牧場上只能建立乙個控制站,每個控制站控制的牧場是它所在的牧場一直到它西邊第乙個控制站的所有牧場 它西邊第乙個控制站所在的牧場不被控制 如...
BZOJ3437 小p的牧場
小p 在mc 裡有n 個牧場,自西向東呈一字形排列 自西向東用1 n 編號 於是他就煩惱了 為了控制這n 個牧場,他需要在某些牧場上面建立控制站,每個牧場上只能建立乙個控制站,每個控制站控制的牧場是它所在的牧場一直到它西邊第乙個控制站的所有牧場 它西邊第乙個控制站所在的牧場不被控制 如果它西邊不存在...