考虑倒推;
可以发现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 ",vv[i]); 51 return 0; 52 }