P2605 [ZJOI2010]基站选址
生活随笔
收集整理的這篇文章主要介紹了
P2605 [ZJOI2010]基站选址
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
P2605 [ZJOI2010]基站選址
?
題目描述
詳見:P2605 [ZJOI2010]基站選址
Solution
首先不難想到一個??? 的DP。
? 表示前個村莊選擇了個基站的總費用。
考慮如何優(yōu)化這個轉(zhuǎn)移。
對于村莊,我們記錄它覆蓋范圍內(nèi)最靠前的村莊????和最靠后的村莊???。
倘若在之后的村莊建立基站,則若上一個基站在之前,那么就會多一個的費用。
增加費用的狀態(tài)是形如?的連續(xù)一段狀態(tài)。
我們只需要讓滾動,維護區(qū)間加,詢問區(qū)間最小值,線段樹維護即可。
?
Ps:luogu題解中很多代碼求?????時使用的是?再特判減1,但這樣如果出現(xiàn)相等的值時,會找到相等的值中第一個值,與??? 的實際意義不符,但由于我太蒟,不知道會不會對答案產(chǎn)生影響qwq。
Code
#include<bits/stdc++.h> using namespace std; const int MAXN=1e5+50; const int INF=0x3f3f3f3f; int d[MAXN],a[MAXN],s[MAXN],w[MAXN],fi[MAXN],la[MAXN],f[MAXN]; vector<int> e[MAXN]; inline int read() {int x=0,f=1; char c=getchar();while (c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f; } struct Segment_Tree {struct segnode{int l,r,tag,mn; } tree[MAXN<<2];void up(int x){ tree[x].mn=min(tree[x<<1].mn,tree[x<<1|1].mn); }void down(int x){if (tree[x].tag!=0){int q=tree[x].tag;tree[x<<1].tag+=q,tree[x<<1].mn+=q;tree[x<<1|1].tag+=q,tree[x<<1|1].mn+=q;tree[x].tag=0;}}void build(int x,int l,int r){tree[x].tag=tree[x].mn=0;if ((tree[x].l=l)==(tree[x].r=r)) {tree[x].mn=f[l];return;}int mid=(l+r)>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);up(x);}int query(int x,int l,int r){if (tree[x].l>=l&&tree[x].r<=r) return tree[x].mn;down(x);int mid=(tree[x].l+tree[x].r)>>1;if (r<=mid) return query(x<<1,l,r);else if (l>mid) return query(x<<1|1,l,r);else return min(query(x<<1,l,mid),query(x<<1|1,mid+1,r));}void change(int x,int l,int r,int y){if (tree[x].l>=l&&tree[x].r<=r){tree[x].mn+=y;tree[x].tag+=y;return;}down(x);int mid=(tree[x].l+tree[x].r)>>1;if (r<=mid) change(x<<1,l,r,y);else if (l>mid) change(x<<1|1,l,r,y);else change(x<<1,l,mid,y),change(x<<1|1,mid+1,r,y);up(x);} } segment; int main() {int n=read(),m=read(); for (int i=2;i<=n;i++) d[i]=read();for (int i=1;i<=n;i++) a[i]=read();for (int i=1;i<=n;i++) s[i]=read();for (int i=1;i<=n;i++) w[i]=read();n++; d[n]=w[n]=INF;for (int i=1;i<=n;i++){fi[i]=lower_bound(d+1,d+n+1,d[i]-s[i])-d;la[i]=upper_bound(d+1,d+n+1,d[i]+s[i])-d-1;//cout<<i<<" "<<fi[i]<<" "<<la[i]<<endl;e[la[i]].push_back(i);}int cnt=0,ans=0;for (int i=1;i<=n;i++){f[i]=cnt+a[i];for (int k=0;k<e[i].size();k++) cnt+=w[e[i][k]];}ans=f[n];//for (int i=1;i<=n;i++) cout<<i<<" "<<f[i]<<endl;cout<<endl;for (int j=2;j<=m+1;j++){segment.build(1,1,n);for (int i=1;i<=n;i++){if (j>i) f[i]=a[i];else f[i]=segment.query(1,j-1,i-1)+a[i];for (int k=0;k<e[i].size();k++) if (fi[e[i][k]]>1) segment.change(1,1,fi[e[i][k]]-1,w[e[i][k]]);}ans=min(ans,f[n]);}printf("%d\n",ans);return 0; }?
?
?
?
總結
以上是生活随笔為你收集整理的P2605 [ZJOI2010]基站选址的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 比你更老的系统重现江湖?探索神秘的Win
- 下一篇: P1600 天天爱跑步