bzoj1034 田忌赛马 题解报告

题目传送门

【题目大意】

有$n$场比赛,给出你的对手每匹马的能力值和你的每匹马的能力值,每场比赛胜利则得两分,平手得一分,输了不得分。求$n$场比赛后你的最大和最小得分。

【思路分析】

设$a$数组记录对手的马的能力值,$b$数组记录你的马的能力值,将两个数组从小到大排序。

首先分析最大得分,我们有这样的贪心策略:

1.如果当前状态下$a_{max}

2.如果当前状态下$a_{min}

3.当上面两个条件都不满足时,就用$b_{min}$去和$a_{max}$比,然后继续上面的步骤

最后即可得出最大得分$ans_1$

对于最小得分,我们可以发现一个规律:无论如何,$n$场比赛结束后两人的总得分为$2*n$,那么可以用上面的方法求出对手的最大得分$ans$,那么最小得分即为$ans_2=2*n-ans$

【代码实现】

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #define g() getchar()
 7 #define rg register
 8 #define go(i,a,b) for(rg int i=a;i<=b;i++)
 9 #define back(i,a,b) for(rg int i=a;i>=b;i--)
10 #define db double
11 #define ll long long
12 #define il inline
13 #define pf printf
14 using namespace std;
15 int fr(){
16     int w=0,q=1;
17     char ch=g();
18     while(ch<'0'||ch>'9'){
19         if(ch=='-') q=-1;
20         ch=g();
21     }
22     while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g();
23     return w*q;
24 }
25 const int N=100002;
26 int n,a[N],b[N],ans1,ans2;
27 int main(){
28     //freopen("","r",stdin);
29     //freopen("","w",stdout);
30     n=fr();
31     go(i,1,n) b[i]=fr();
32     go(i,1,n) a[i]=fr();
33     sort(a+1,a+1+n);sort(b+1,b+1+n);
34     rg int la=1,ra=n,lb=1,rb=n;
35     while(la<=ra&&lb<=rb){
36         while(la<=ra&&lb<=rb&&a[ra]2;
37         while(la<=ra&&lb<=rb&&a[la]2;
38         if(a[ra]==b[lb]) ans1++;
39         lb++;ra--;
40     }
41     la=lb=1;ra=rb=n;
42     while(la<=ra&&lb<=rb){
43         while(la<=ra&&lb<=rb&&a[ra]>b[rb]) ra--,rb--,ans2+=2;
44         while(la<=ra&&lb<=rb&&a[la]>b[lb]) la++,lb++,ans2+=2;
45         if(a[la]==b[rb]) ans2++;
46         la++;rb--;
47     }
48     ans2=2*n-ans2;
49     pf("%d %d\n",ans1,ans2);
50     return 0;
51 }
代码戳这里

你可能感兴趣的:(bzoj1034 田忌赛马 题解报告)