ICPCCamp 2016 Day 6 - Spb SU and Spb AU Contest(Greedy Game-贪心)

n105 个物品,每个物品有价值 ai,bi ,现在2人轮流取值,先手的策略是从 ai 最大的物品中任取一个,问后手可能取得的最大 bi

把元素按 ai 为第一关键字, bi 为第二关键字排序,现在每次先手都取最前的

我们考虑截至到前n-1个时的最优解已知,考虑第n个
显然如果n是第偶数个那么必取,
n是第奇数个时,考虑如果取这个数,只要拿之前取的任意一个换(显然仍合法)
可以用反证法证明贪心正确。

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <functional>
#include <cstdlib>
#include <queue>
#include <stack>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define Rep(i, n) for (int i = 1; i <= (n); ++i)
#define FOR(i, c) for(__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define clr(x, a) memset(x, (a), sizeof x)
#define RD(x) scanf("%d", &x)
#define PB push_back
#define MP make_pair
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
ll ans=0;
struct node{
  int a,b,ranka,rankb;
}p[2000000];
int cmpa(node a,node b){
  if (a.a==b.a) return a.b>b.b;
  return a.a>b.a;
}
int cmpb(node a,node b){
  if (a.b==b.b) return a.a>b.a;
  return a.b>b.b;
}
int n;
priority_queue<int,vector<int>,greater<int> > q;
int main() {
  scanf("%d",&n);
  for (int i=1;i<=n;i++)
    scanf("%d",&p[i].a);
  for (int i=1;i<=n;i++)
    scanf("%d",&p[i].b);
  sort(p+1,p+1+n,cmpa);
  for (int i=1;i<=n;i++) p[i].ranka=i;

  ans=0;
  for(int i=2;i<=n;i+=2) ans+=p[i].b;
  for(int i=2;i<=n;i+=2) {
      q.push(p[i].b); 
      if (!q.empty()) {
          int top=q.top();
          if (i<n) if (top < p[i+1].b ) q.pop(),q.push(p[i+1].b),ans=ans+p[i+1].b-top;
      }
  } 
  cout<<ans<<endl;

 return 0;
}

你可能感兴趣的:(ICPCCamp 2016 Day 6 - Spb SU and Spb AU Contest(Greedy Game-贪心))