題面
設 \(f[i,j]\) 表示前 i 個村莊建立 j 個基站,且第 i 個村莊有基站的最小花費
則有 \(f[i,j]=min_\\) 其中 \(cost(k,i)\) 表示第 i ,k 個村莊建有基站,中間沒有,所需要補償的費用
發現轉移式中從 j-1 -> j ,我們可以脫去 j 這一維
考慮怎麼計算 \(cost(k,i),k< i\) 。如果村莊 \(a\) 產生補償費,當且僅當它沒有被覆蓋到,那麼我們可以預處理出 **能夠覆蓋到 \(a\) 的最小和最大的村莊 \(st_a\)
\(ed_a\) ** ,當 \(i\) 覆蓋不到 \(a\) ,也即\(i>ed_a\) 的時候,就把從 1 到 \(st_a-1\) 的村莊的 \(cost\) 都加上 \(w_a\)
我們要支援乙個區間加的操作,和乙個區間取最小值的操作。可用線段樹維護\(f+cost\) 來實現
#includeusing namespace std;
#define int long long
int const maxn=400000,inf=0x7fffffffffff;
int n,k,d[maxn],c[maxn],s[maxn],w[maxn],st[maxn],ed[maxn];
int tot,h[maxn],f[maxn],ans;
struct edgee[maxn];
int read()
while(isdigit(c))
return x*f;
}void add(int u,int x),h[u]=tot;
}struct segment_tree
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
a[x]=min(a[x<<1],a[x<<1|1]);
return;
} void pushdown(int x)
return;
} void change(int x,int l,int r,int v)
pushdown(x);
int mid=(l[x]+r[x])>>1;
if(l<=mid)change(x<<1,l,r,v);
if(r>mid)change(x<<1|1,l,r,v);
a[x]=min(a[x<<1],a[x<<1|1]);
} int query(int x,int l,int r)
pushdown(x);
int mid=(l[x]+r[x])>>1;
int ans=inf;
if(l<=mid)ans=min(ans,query(x<<1,l,r));
if(r>mid)ans=min(ans,query(x<<1|1,l,r));
a[x]=min(a[x<<1],a[x<<1|1]);
return ans;
}}tree;
signed main()
n++,k++;w[n]=d[n]=inf;
for(int i=1;i<=n;i++)
} ans=min(ans,f[n]);
} printf("%lld\n",ans);
return 0;
}
LG4948 題解報告
p4948 題解報告 求 sum 的值,其中 n le10 k le 2 times 10 3,a le 10 9 本題在 具體數學 一書中有詳細的解法思路說明,可以在該書第二章 和式 中得到思路的啟發。對這個式子進行擾動。令 s k sum 當 a 1 時,有 s k sum sum i 1 k ...
題解 lg2034 選擇數字
給定一行n個非負整數a 1 a n 現在你可以選擇其中若干個數,但不能有超過k個連續的數字被選擇。你的任務是使得選出的數字的和最大。設 f i,0 表示考慮到數字 i 並選擇 i 的最大和,f i,1 表示考慮到數字 i 並選擇 i 的最大和 那麼 f i,0 min f i 1,0 f i 1,1...
題解 lg2480 古代豬文
給定整數 q,n 1 leq q,n leq 10 9 求 q c mod 999911659 首先由擴充套件尤拉定理可知,因為999911659為質數 q c equiv q c mod 999911658 mod 999911659 設 x sum c mod 999911658 然後再 由於 ...