[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。

posted @ 2017-05-16 16:08  skylee03  阅读(138)  评论(0编辑  收藏  举报