有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di。需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci。如果在距离第i个村庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了。如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi。现在的问题是,选择基站的位置,使得总费用最小。 输入数据 (base.in) 输入文件的第一行包含两个整数N,K,含义如上所述。 第二行包含N-1个整数,分别表示D2,D3,…,DN ,这N-1个数是递增的。 第三行包含N个整数,表示C1,C2,…CN。 第四行包含N个整数,表示S1,S2,…,SN。 第五行包含N个整数,表示W1,W2,…,WN。
3 2 1 2 2 3 2 1 1 0 10 20 30
1 #include<cstdio>
2 #include<vector>
3 #include<cstring>
4 #include<algorithm>
5 #define lll spc<<1
6 #define rrr spc<<1|1
7 typedef long long lnt;
8 const int N=30010;
9 struct trnt{
10 lnt lzt;
11 lnt minv;
12 }tr[N<<2],stt;
13 int n,k;
14 lnt w[N],s[N],d[N],c[N];
15 int lp[N],rp[N];
16 lnt dp[N];
17 std::vector<lnt>lim[N];
18 void pushup(int spc)
19 {
20 tr[spc].minv=std::min(tr[lll].minv,tr[rrr].minv);
21 return ;
22 }
23 void add(int spc,lnt v)
24 {
25 tr[spc].minv+=v;
26 tr[spc].lzt+=v;
27 return ;
28 }
29 void pushdown(int spc)
30 {
31 if(tr[spc].lzt)
32 {
33 add(lll,tr[spc].lzt);
34 add(rrr,tr[spc].lzt);
35 tr[spc].lzt=0;
36 }
37 return ;
38 }
39 void build(int l,int r,int spc)
40 {
41 tr[spc]=stt;
42 if(l==r)
43 {
44 tr[spc].minv=dp[l];
45 return ;
46 }
47 int mid=(l+r)>>1;
48 build(l,mid,lll);
49 build(mid+1,r,rrr);
50 pushup(spc);
51 return ;
52 }
53 void update(int l,int r,int ll,int rr,int spc,lnt v)
54 {
55 if(l>rr||ll>r)
56 return ;
57 if(ll<=l&&r<=rr)
58 {
59 add(spc,v);
60 return ;
61 }
62 int mid=(l+r)>>1;
63 pushdown(spc);
64 update(l,mid,ll,rr,lll,v);
65 update(mid+1,r,ll,rr,rrr,v);
66 pushup(spc);
67 return ;
68 }
69 lnt query(int l,int r,int ll,int rr,int spc)
70 {
71 if(l>rr||ll>r)
72 return 0x3f3f3f3f;
73 if(ll<=l&&r<=rr)
74 return tr[spc].minv;
75 int mid=(l+r)>>1;
76 pushdown(spc);
77 return std::min(query(l,mid,ll,rr,lll),query(mid+1,r,ll,rr,rrr));
78 }
79 int main()
80 {
81 scanf("%d%d",&n,&k);
82 for(int i=2;i<=n;i++)
83 scanf("%lld",&d[i]);
84 for(int i=1;i<=n;i++)
85 scanf("%lld",&c[i]);
86 for(int i=1;i<=n;i++)
87 scanf("%lld",&s[i]);
88 for(int i=1;i<=n;i++)
89 scanf("%lld",&w[i]);
90 for(int i=1;i<=n;i++)
91 {
92 lp[i]=rp[i]=i;
93 int l=1,r=i-1;
94 while(l<=r)
95 {
96 int mid=(l+r)>>1;
97 if(d[i]-d[mid]<=s[i])
98 {
99 r=mid-1;
100 lp[i]=mid;
101 }else
102 l=mid+1;
103 }
104 l=i+1,r=n;
105 while(l<=r)
106 {
107 int mid=(l+r)>>1;
108 if(d[mid]-d[i]<=s[i])
109 {
110 l=mid+1;
111 rp[i]=mid;
112 }else
113 r=mid-1;
114 }
115 lim[rp[i]].push_back(i);
116 }
117 lnt sum=0;
118 for(int i=1;i<=n;i++)
119 {
120 dp[i]=c[i]+sum;
121 for(int j=0;j<lim[i].size();j++)
122 sum+=w[lim[i][j]];
123 }
124 lnt ans=sum;
125 for(int i=1;i<=k;i++)
126 {
127 build(1,n,1);
128 for(int j=1;j<=n;j++)
129 {
130 dp[j]=query(1,n,1,j-1,1)+c[j];
131 for(int o=0;o<lim[j].size();o++)
132 update(1,n,1,lp[lim[j][o]]-1,1,w[lim[j][o]]);
133 }
134 ans=std::min(ans,query(1,n,1,n,1));
135 }
136 printf("%lld\n",ans);
137 return 0;
138 }