noip2015pj t4

来源:互联网 发布:洛阳广电网络客服电话 编辑:程序博客网 时间:2024/04/29 23:45

由于前三题都太水所以懒的写题解。最后一题还是蛮有意思的,虽然数据也很水,我用了一种倒过来的贪心。先做出全部选的状态,再删去一个使得减少的最少,以此类推。每次删去有两种策略,删除最远的点和堆中最小的点(堆里各个点的大小顺序始终不变的)复杂度为nlog2n;但是我没证明为什么选4个的最优解一定包含了选3个的最优解虽然反过来做的时候感觉这是理所当然的。。。

这里写代码:#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
int n,h;
vector<int>  ans;
int dis[100005],va[100005];
bool flag[100005];
int next;
struct p
{int x;
int num;
 bool operator <(p const  &a)const
 { return x>a.x;}
};
priority_queue <p> q;
int main()
{freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
int sum=0; 
cin>>n;
  for(int i=1;i<=n;i++)
    scanf("%d",&dis[i]); 
  
  for(int i=1;i<=n;i++)
 {  scanf("%d",&va[i]);sum=sum+va[i];
  q.push((p){va[i],i});}
   sum=sum+dis[n]*2;
    ans.push_back(sum);
    int last=n;next=n-1;
    int cnt=0;
    while(cnt<n-1)
     {    p k=q.top();
     if(k.num>=last)
        { q.pop();
        continue;
        }
     if(k.x<(dis[last]-dis[next])*2+va[last])
       { flag[k.num]=true;
       cnt++;
        q.pop();
        sum=sum-k.x;
       ans.push_back(sum);
        while(flag[next]==true) next--;
  }
  else
  { sum=sum-((dis[last]-dis[next])*2+va[last]);
    ans.push_back(sum);
  cnt++; 
   last=next;next--;
    while(flag[next]==true) next--;
  }
          
     }
     for(int i=ans.size()-1;i>=0;i--)
        printf("%d\n",ans[i]);
return 0;
}

0 0
原创粉丝点击