如果当前点在最大距离点左边,只加上推销疲劳值
如果当前点在最大距离点右边,还要在加上两倍距离差,并更新最大距离点
首先很容易想到一个贪心:找在最大距离左边最优的点与右边最优的点进行比较(写成程序就是两个if),取最优。
并且还要判断该点没有去过。
最后如果取了右边的点要更新最大距离点。于是有了这份程序:
#include<bits/stdc++.h> using namespace std; int n; struct node{ int dis;//距离 int num;//推销疲劳值 }peo[100007]; bool vis[100007];//记录有没有去过 int maxnum;//最大距离点 int ans; int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>peo[i].dis; for(int i=1;i<=n;i++) cin>>peo[i].num; for(int i=1;i<=n;i++){ int maxn=0,maxi=0,k=0; //总的最优情况,此时编号,两种情况的最优 for(int j=1;j<=n;j++){ if(!vis[j]){ if(j<maxnum){ k=max(k,peo[j].num);//最大距离点左边 } else { k=max(k,peo[j].num+(peo[j].dis-peo[maxnum].dis)*2);//最大距离点右边 } if(k>maxn){//更新此时最优点 maxn=k; maxi=j; } } } maxnum=max(maxnum,maxi);//更新最大距离点 vis[maxi]=true; ans+=k; cout<<ans<<endl;//每次都要输出 } return 0; }然后能得到60分(加上快读和加ios的cout也没用)
其实已经很好了对我这个蒟蒻来说
然后就是针对剩余4个点的优化了。需要用到优先队列(我们教练告诉我的),后来看别的题解发现还可用反贪,但是我不会
定义优先队列ql,qr。ql存最大距离点左边的,qr存最大距离点右边的(只是存的时候这么存)
每次都取最大值,然后出队。在两个点中取最优,如果去qr的点,要更新最大距离点。同时判断有没有去过,若去过,也舍弃。注意:若qr的点跑到了最大距离点左边,那么这个点应该舍弃,但若ql的点跑到了最大距离点右边,不应舍弃,因为它仍有机会跑到最大距离点左边(有可能后来更新了最大距离点)。
当是第一次走的时候特判,必定走qr的点(这样才能有一个最大距离点)
#include<bits/stdc++.h> using namespace std; int n; int maxdis;//最大距离点的距离 struct node{ int dis;//ql里是推销值,qr里还要加上两倍距离 int num;//编号 bool operator < (const node &x) const{ return dis<x.dis;//重载运算符,没有为什么,我也是学的别的题解里的 } }; int ans; int dis[100007];//每个点的距离 int num[100007];//每个点的推销疲劳值 bool vis[100007];//同上 priority_queue<node,vector<node>,less<node> > qr,ql;//命名是套路 int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>dis[i]; for(int i=1;i<=n;i++){ cin>>num[i]; node k; k.num=i; k.dis=num[i]; ql.push(k); k.dis=num[i]+2*dis[i]; qr.push(k); //每个节点分别入两队 } vis[qr.top().num]=true; ans=qr.top().dis; cout<<ans<<endl; //第一个点肯定是离起点最远的那个(推销疲劳值已经加进去了) maxdis=dis[qr.top().num];//存下最远距离 if(ql.top().num==qr.top().num)ql.pop();//如果该点在两个队列中都出现了,都要出队 qr.pop(); for(int i=2;i<=n;i++){ node maxl=ql.top(),maxr=qr.top(); if(vis[maxl.num]){ql.pop();i--;continue;}//队首已经去过了,舍去 if(vis[maxr.num]){qr.pop();i--;continue;}//同上 //记得i要--,不然相当于取了一个点,答案却没有加上 if((maxl.dis>=(maxr.dis-2*maxdis))||((maxr.dis-num[maxr.num])<2*maxdis)){ //这里是取两个中的最优点,有没有=均可 此处是取qr的距离 qr的点得在最大距离点右边 ans+=maxl.dis; ql.pop(); } else { ans+=maxr.dis-2*maxdis; maxdis=dis[maxr.num];//更新最大距离点 qr.pop(); } cout<<ans<<endl;//每次输出答案 } return 0; }