[luogu]P2123 皇后游戏[贪心,排序算法理解]

题目

给定T组数据,每组数据n组\{ a,b \}值,选定合理序列使max \{ c_{i} \}最小

其中c_{i}=max\{ c_{i-1}, \sum_{k=1}^{i}a_{k} \} + b_{i},特别的c_{1}=a_{1}+b_{1}

数据范围:T\leq10,1\leq n \leq20000, 1\leq a_{i},b_{i} \leq 10^{9}

贪心策略

易知c_{x}严格递增,故max \{ c_{x} \}=c_{n}

假设前n项已经为最优序列\{ 1,2,...n \},考虑新加入元素n+1

观察c_{x}结构可知,调换相邻两项不影响最前面已经排好的序列的值

考虑\{1,2...n,n+1\}\{1,2...n+1,n\}两个序列的c_{max},c_{max}^{'}两值

pre_{n}=\sum_{i=1}^{n}a_{i}

c_{max} \\=max \{ c_{n},pre_{n+1} \}+b_{n+1} \\=max \{ \{c_{n-1},pre_{n} \} +b_{n} ,pre_{n+1} \}+b_{n+1} \\=max \{ c_{n-1} + b_{n}, pre_{n} + b_{n}, pre_{n+1} \} + b_{n+1} \\=max \{c_{n-1},pre_{n},pre_{n-1} - b_{n}\} + b_{n} + b_{n+1} (最后一行应该是pre_{n+1}-b_{n})

c_{max}^{'}=max \{c_{n-1},pre_{n+1}-a_{n},pre_{n+1} -b_{n+1} \}+b_{n+1}+b_{n}

c_{max} > c_{max}^{'}\\ <=> max \{ pre_{n+1}-a_{n+1}, pre_{n+1}-b{n} \} > max \{ pre_{n+1}-a_{n}, pre_{n+1}-b_{n+1} \}\\ <=> max \{ -a_{n+1}, -b_{n} \} > max \{ -a_{n}, -b_{n+1} \}\\ <=> min \{ a_{n+1}, b_{n} \} < min \{ a_{n}, b_{n+1} \}\\ <=> \( a_{n+1}<a_{n} \wedge a_{n+1}<b_{n+1} \) \vee \( b_{n}<a_{n} \wedge b_{n}<b_{n+1} \)\\ \\ \\ \\ ......(*)

由此不等式可以看出问题可能具有最优子结构,且可以直接进行贪心的选择

注意:不可直接用等式min \{a_{n+1},b_{n} \} < min \{a_{n}, b_{n+1} \}进行排序,该不等式不具有传递性,也就是说直接排序后序列不一定最优

2
7
6 3
1 1
7 3
1 1
1 6
1 1
6 10

7
6 10
1 1
6 3
1 1
7 3
1 1
1 6

(一组hack数据)

分析上述(*)式的结构,可以看出不等式与\(a_{x}-b_{x} \)值的正负密切相关,这里引入d_{x}=sgn \(a_{x}-b_{x} \)

1°对于d_{x}值相等的集合中,不等式存在明显的传递性

2°若d_{x} \neq d_{y},不妨d_{x} < d_{y}, 则d_{x} \in \{-1,0 \}, d_{y} \in \{0,1 \}=> a_{x} \leq b_{x}, a_{y} \geq b_{y}

=> \(a_{y} - a_{x} \) + \(b_{x} - b_{y} \) \geq 0 => (a_{y} - a_{x}) \geq 0 \vee (b_{x} - b_{y}) \geq 0上述(*)成立

3°故可先对d_{x}值不同进行分类,在对相等的值进行排序

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

using LL = long long;
int T, N;
struct node {
  LL a, b, c, d;
} p[20005];
LL pre[20005];
int sgn(int);
bool cmp(node, node);
LL ans;

int main(){
  ios::sync_with_stdio(false);
  cin >> T;
  while(T--){
    cin >> N;
    int i;
    for(i = 1; i <= N; i++)
      cin >> p[i].a >> p[i].b, p[i].d = sgn(p[i].a - p[i].b);
    sort(p + 1, p + 1 + N, cmp);
    for(i = 1; i <= N; i++) pre[i] = pre[i - 1] + p[i].a;
    for(i = 1; i <= N; i++)
      p[i].c = max(p[i - 1].c, pre[i]) + p[i].b;
    cout << p[N].c << endl;
  }
  return 0;
}

int sgn(int x){
  if(!x) return x;
  return (x > 0) ? 1 : -1;
}

bool cmp(node x, node y){
  if(x.d != y.d) return x.d < y.d;
  if(x.d <= 0) return x.a < y.a;
  else return y.b < x.b;
}

猜你喜欢

转载自blog.csdn.net/Hardict/article/details/82356608
今日推荐