[NOIp2015普及组]推销员
OJ题号:洛谷P2672
思路:
贪心。每次把住户分为左右两部分。对于左边,每次的代价为$a_i$。对于右边,每次增加的代价为$s_i*2+a_i$。每次挑代价最大的住户加到答案中。
60分代码:直接暴力贪心(初二上学期写的代码,所以是 Pascal )。
1 uses 2 math; 3 var 4 n,i,j,t:longint; 5 s,a:array[1..100000]of longint; 6 f,d:array[boolean]of longint; 7 b:array[1..100000]of boolean; 8 begin 9 readln(n); 10 for i:=1 to n do begin 11 read(s[i]) 12 end; 13 readln; 14 for i:=1 to n do begin 15 read(a[i]) 16 end; 17 readln; 18 fillchar(f,sizeof(f),0); 19 fillchar(d,sizeof(d),0); 20 fillchar(b,sizeof(b),0); 21 for i:=1 to n do begin 22 for j:=1 to n do begin 23 if f[odd(i)]<(f[not odd(i)]+a[j]+max(s[j]-d[not odd(i)],0)<<1)*longint(not b[j]) then begin 24 f[odd(i)]:=f[not odd(i)]+a[j]+max(s[j]-d[not odd(i)],0)<<1; 25 d[odd(i)]:=max(s[j],d[not odd(i)]); 26 t:=j 27 end 28 end; 29 b[t]:=true; 30 writeln(f[odd(i)]) 31 end 32 end.
AC代码:优先队列优化。
1 #include<cstdio> 2 #include<cstring> 3 #include<utility> 4 #include<ext/pb_ds/priority_queue.hpp> 5 __gnu_pbds::priority_queue<std::pair<int,int> > l,r; 6 int main() { 7 int n; 8 scanf("%d",&n); 9 int s[n],a[n]; 10 bool u[n]; 11 memset(u,0,sizeof u); 12 for(int i=0;i<n;i++) scanf("%d",&s[i]); 13 for(int i=0;i<n;i++) scanf("%d",&a[i]); 14 for(int i=0;i<n;i++) r.push(std::make_pair(s[i]*2+a[i],i)); 15 int ans=0; 16 for(int i=0;i<n;i++) { 17 while(!r.empty()&&u[r.top().second]) r.pop(); 18 if(!l.empty()&&!r.empty()) { 19 if(l.top().first>r.top().first) { 20 ans+=l.top().first; 21 l.pop(); 22 } 23 else { 24 ans+=r.top().first; 25 u[r.top().second]=true; 26 for(int i=0;i<r.top().second;i++) { 27 if(u[i]) continue; 28 u[i]=true; 29 l.push(std::make_pair(a[i],i)); 30 } 31 r.pop(); 32 } 33 goto Ans; 34 } 35 if(l.empty()) { 36 ans+=r.top().first; 37 u[r.top().second]=true; 38 for(int i=0;i<r.top().second;i++) { 39 if(u[i]) continue; 40 u[i]=true; 41 l.push(std::make_pair(a[i],i)); 42 } 43 r.pop(); 44 goto Ans; 45 } 46 if(r.empty()) { 47 ans+=l.top().first; 48 l.pop(); 49 } 50 Ans: 51 printf("%d\n",ans); 52 } 53 return 0; 54 }
另外本题还有线段树、树状数组等方法可以AC。