最近状态太差,先补补结题报告吧
这是一道好题
设f[i,j]表示到第j个位置建了i个基站且第j个位置建了基站的最小花费
不难得到f[i,j]=min(f[i-1,k]+cost[k+1,j])+c[j];
首先为了方便计算假定在两端无穷远处还要建一个基站(方便统计)
i我们是可以滚动的不管他,问题就是如何解决cost
也就是两个基站间的村庄的补偿费
我们设每个村庄i向左最远能收到l[i]位置上基站的信号,向右最远r[i]
不难发现,随着j的递增,cost[k]是呈上升趋势的
也就是,对于当前j,那些r[p]<j的点p,向右是永远收不到信号了,
向左对于在位置k∈[0,l[p]-1]的基站,随着j增加以k,j为端点建基站对于p是永远要收补偿费的
于是我们令cost[k]表示(k建基站)到当前点之间村庄要收补偿费的和
对于当前点j,我们找出r[p]+1=j的点p,对于k∈[0,l[p]-1] cost[k]+w[p]
显然是区间查询,区间修改的问题,我们可以用线段树解决
复杂度O(knlogn)
1 type node=record 2 po,next:longint; 3 end; 4 5 var f,c,d,p,w,s,l:array[0..20010] of longint; 6 e:array[0..20010] of node; 7 tree,lazy:array[0..20010*4] of longint; 8 ans,n,m,i,j,k,t,x:longint; 9 10 function min(a,b:longint):longint; 11 begin 12 if a>b then exit(b) else exit(a); 13 end; 14 15 procedure update(i:longint); 16 begin 17 tree[i]:=min(tree[i*2],tree[i*2+1]); 18 end; 19 20 procedure push(i:longint); 21 begin 22 inc(lazy[i*2],lazy[i]); 23 inc(lazy[i*2+1],lazy[i]); 24 inc(tree[i*2],lazy[i]); 25 inc(tree[i*2+1],lazy[i]); 26 lazy[i]:=0; 27 end; 28 29 function fl(l,r,x:longint):longint; 30 var m:longint; 31 begin 32 fl:=r; 33 while l<=r do 34 begin 35 m:=(l+r) shr 1; 36 if d[m]>=x then 37 begin 38 fl:=m; 39 r:=m-1; 40 end 41 else l:=m+1; 42 end; 43 end; 44 45 function fr(l,r,x:longint):longint; 46 var m:longint; 47 begin 48 fr:=l; 49 while l<=r do 50 begin 51 m:=(l+r) shr 1; 52 if d[m]<=x then 53 begin 54 fr:=m; 55 l:=m+1; 56 end 57 else r:=m-1; 58 end; 59 end; 60 61 procedure build(i,l,r:longint); 62 var m:longint; 63 begin 64 lazy[i]:=0; 65 if l=r then 66 begin 67 tree[i]:=f[l]; 68 lazy[i]:=0; 69 end 70 else begin 71 m:=(l+r) shr 1; 72 build(i*2,l,m); 73 build(i*2+1,m+1,r); 74 update(i); 75 end; 76 end; 77 78 procedure work(i,l,r,x,y:longint); 79 var m:longint; 80 begin 81 if r<=x then 82 begin 83 inc(lazy[i],y); 84 inc(tree[i],y); 85 end 86 else begin 87 if lazy[i]<>0 then push(i); 88 m:=(l+r) shr 1; 89 work(i*2,l,m,x,y); 90 if x>m then work(i*2+1,m+1,r,x,y); 91 update(i); 92 end; 93 end; 94 95 function ask(i,l,r,x:longint):longint; 96 var m,s:longint; 97 begin 98 if r<=x then exit(tree[i]) 99 else begin 100 if lazy[i]<>0 then push(i); 101 m:=(l+r) shr 1; 102 s:=ask(i*2,l,m,x); 103 if x>m then s:=min(s,ask(i*2+1,m+1,r,x)); 104 exit(s); 105 end; 106 end; 107 108 begin 109 readln(n,m); 110 for i:=2 to n do 111 read(d[i]); 112 for i:=1 to n do 113 read(c[i]); 114 for i:=1 to n do 115 read(s[i]); 116 for i:=1 to n do 117 begin 118 read(w[i]); 119 ans:=ans+w[i]; 120 end; 121 for i:=1 to n do 122 begin 123 l[i]:=fl(1,i,d[i]-s[i]); 124 x:=fr(i,n,d[i]+s[i]); 125 inc(t); 126 e[t].po:=i; 127 e[t].next:=p[x+1]; 128 p[x+1]:=t; 129 end; 130 for i:=1 to m do 131 begin 132 build(1,0,n); 133 for j:=1 to n+1 do 134 begin 135 k:=p[j]; 136 while k<>0 do 137 begin 138 work(1,0,n,l[e[k].po]-1,w[e[k].po]); 139 k:=e[k].next; 140 end; 141 if i=1 then x:=0 else x:=j-1; 142 f[j]:=ask(1,0,n,x)+c[j]; 143 end; 144 ans:=min(ans,f[n+1]); 145 end; 146 build(1,0,n); 147 for j:=1 to n+1 do 148 begin 149 k:=p[j]; 150 while k<>0 do 151 begin 152 work(1,0,n,l[e[k].po]-1,w[e[k].po]); 153 k:=e[k].next; 154 end; 155 end; 156 ans:=min(ans,ask(1,0,n,n)); 157 writeln(ans); 158 end.