洛谷 P2672 推销员

考虑倒推;

可以发现X=i时的最优解,一定可以由X=i+1时的最优解去掉一户人家得到,

这是因为,只可能去掉疲劳值最小的或者第二小的(如果最小的在最右侧,那么就有可能是第二小的),

可以发现,对一组解连续做k次这样的去掉操作,跟一次性去掉k个是一样优的,

那么,X=i的答案,原来需要一次性去掉n-i个,可以改为逐个去掉,就相当于从X=i+1的答案变过来。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 #include<set>
 6 using namespace std;
 7 #define fi first
 8 #define se second
 9 #define mp make_pair
10 #define pb push_back
11 typedef pair<int,int> pi;
12 pi q[100100];
13 int n,ans;
14 vector<int> vv;
15 multiset<pi> s;
16 multiset<pi>::iterator ittt[100100];
17 multiset<int> s2;
18 int main()
19 {
20     int i,a=0,b=0,a1,b1,c,c1;
21     scanf("%d",&n);
22     for(i=1;i<=n;i++)    scanf("%d",&q[i].fi),q[i].fi*=2,s2.insert(q[i].fi);
23     for(i=1;i<=n;i++)    scanf("%d",&q[i].se),ans+=q[i].se,ittt[i]=s.insert(mp(q[i].second,i));
24     ans+=q[n].fi;
25     vv.pb(ans);
26     for(i=2;i<=n;i++)
27     {
28         auto it=s.begin();
29         a=it->se;
30         it++;
31         b=it->se;
32         
33         a1=*s2.rbegin();
34         s2.erase(s2.find(q[a].first));
35         a1-=*s2.rbegin();
36         s2.insert(q[a].first);
37         a1+=q[a].second;
38         
39         b1=*s2.rbegin();
40         s2.erase(s2.find(q[b].first));
41         b1-=*s2.rbegin();
42         s2.insert(q[b].first);
43         b1+=q[b].second;
44             
45         if(a1<b1)    c=a,c1=a1;
46         else    c=b,c1=b1;
47         ans-=c1;s.erase(ittt[c]);s2.erase(s2.find(q[c].fi));
48         vv.pb(ans);
49     }
50     for(i=n-1;i>=0;i--)    printf("%d\n",vv[i]);
51     return 0;
52 }

猜你喜欢

转载自www.cnblogs.com/hehe54321/p/9259410.html