洛谷 2672

来源:互联网 发布:网络诋毁公司如何处理 编辑:程序博客网 时间:2024/05/02 03:02

    首先我们考虑x=n的情况,这个答案是唯一确定的,那么当x=n-1时,我们就需要删去一家用户,那么我们要保证删掉后减少的疲劳值最小,对于最后一家用户,如果删掉它的话,减少的疲劳值就是pl[i]+(s[i]-s[pre[i]])*2,对于其他用户减少的疲劳值就是pl[i],那么我们考虑x=k是否一定是从x=k+1的最优解删除一家用户得来,如果x=k的最优解不是由x=k+1的最优解删除得到,那么在x=k的最优解中加入一家用户一定可以更新x=k+1的最优解。因此我们知道了x=k一定是由x=k+1删除一家用户得到,这样我们删除的用户一定是min(pl[i],pl[cur]+(s[cur]-s[pre[cur]])*2),其中cur是位置最靠后的用户,我们可以提前按pl[i]排序,然后用链表维护cur就可以。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define maxn 100005int pre[maxn],next[maxn];int n,s[maxn],cur,ans[maxn],p,temp,pl[maxn];bool vis[maxn];struct Vergil{int key,id;}t[maxn];bool cmp(Vergil a,Vergil b) {return a.key<b.key;}int main(){scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",s+i);for (int i=1;i<=n;i++) {t[i].id=i;scanf("%d",&pl[i]);t[i].key=pl[i];temp+=t[i].key;}temp+=s[n]*2;ans[n]=temp;sort(t+1,t+n+1,cmp);for (int i=1;i<=n;i++) {pre[i]=i-1;next[i]=i+1;}next[n]=0;cur=n;p=1;for (int i=n-1;i>=1;i--) {while (cur==t[p].id||vis[t[p].id]) p++;if (t[p].key<=(s[cur]-s[pre[cur]])*2+pl[cur]) {temp-=t[p].key;int od=t[p].id;next[pre[od]]=next[od];pre[next[od]]=pre[od];p++;}else {temp-=(s[cur]-s[pre[cur]])*2+pl[cur];vis[cur]=1;next[pre[cur]]=0;cur=pre[cur];}ans[i]=temp;}for (int i=1;i<=n;i++) printf("%d\n",ans[i]);return 0;}


0 0
原创粉丝点击