最近状态太差,先补补结题报告吧
这是一道好题
设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.
View Code

 

 

posted on 2015-01-26 19:05  acphile  阅读(305)  评论(0编辑  收藏  举报