卡牌分组([AtCoder ARC073]Ball Coloring)

Posted Sinogi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了卡牌分组([AtCoder ARC073]Ball Coloring)相关的知识,希望对你有一定的参考价值。

1. 题目描述:
前两道题说了东东和东东爸过去的故事, 现在我们就预测东东未来几年在小学的生活。
小东东上小学时也许会喜欢一种玩具——卡牌。 这里为了出这道题就设每张卡牌只有一个非负整数属性值。 有一天, 小东东买了N包卡牌,每包里有两张卡牌( 设有一张卡片的属性值是xi,另一张的属性值是yi) (就是说小东东一共买了2N张卡牌) 。 小东东要把每包里的两张卡牌都分开,并分别放到左右两堆(如果认为描述不清楚请仔细食用样例) 。
小东东定义了以下的一些数值:
Lmax:放在小东东左边卡牌堆里的卡牌中属性值最大的卡牌的属性值

 

2. 输入:
第一行一个整数N表示小东东买了N包卡牌。
接下来有N行,每行包含两个正整数xi, yi表示第i行的两张卡牌的属性值。


3. 输出:
一个整数表示最小的(Rmax ? Rmin)×(Lmax ? Lmin)。

 

4. 样例:


样例输入1:
3
1 2
3 4
5 6
样例输出1:
15
样例1解释:
最佳方案:x1,x2,y3在左边堆, y1,y2,x3在右边堆。


样例输入2:
3
1010 10
1000 1
20 1020
样例输出2:
380
样例2解释:
一种最佳方案:y1,y2,x3在左边堆, x1,x2,y3在右边堆。


5. 范围:
对于0%的数据与样例一样。
对于32%的数据1 ≤ N ≤ 10
对于另外32%的数据的答案Rmin > Lmax (所有大牌在同一堆, 所有小牌在同一堆)
对于另外36%的数据1 ≤ N ≤ 200,000
对于100%的数据1 ≤ xi , yi ≤ 109
Lmin:放在小东东左边卡牌堆里的卡牌中属性值最小的卡牌的属性值
Rmax:放在小东东右边卡牌堆里的卡牌中属性值最大的卡牌的属性值
Rmin:放在小东东右边卡牌堆里的卡牌中属性值最小的卡牌的属性值
小东东肯定想知道可以算出的最小的(Rmax ? Rmin)×(Lmax ? Lmin)。 但是小东东要玩耍,所以就把这个有趣的任务交给了你。

 

 

此题在算法上没什么技术含量,基本是数学讨论;

答案由四个变量构成,而对于一组数据,一定有MAX_W,MIN_W(所有属性值中最大、最小值)分别是定值;

而Lmax(或Rmax)=MAX_W,Lmin(或Rmin)=MIN_W;

所以有两种情况:

  ①MAX_W与MIN_N在不同侧:(假设MAX在左,MIN在右)

    这种情况十分容易处理。左堆上边界固定,右堆下边界固定,因此这种情况下只需要让左堆的值尽量大,右堆的值尽量小;

    即对于任意一对属性值,较大值放在左堆,较小值放在右堆,结束;

  ②MAX_W与MAX_N在同侧:(假设MAX与MIN同在左)

    这种情况处理方式较为繁琐。左堆上下边界固定,因此只需计算 Rmax-Rmin 的最小值;

    关于枚举方式,首先把属性值大值放左堆,小值放右堆(同①),然后根据右堆属性值由小到大排序(当然反过来也可以);

    然后从上到下依次交换左右属性值(交换第一次时MIN_N被换到了左堆);

    关于正确性,排序之后,任意一个左堆属性值Lw[a]一定大于右堆中下标<=a的值;

    即交换后不会导致Rmin减小,但有可能使Rmax和Rmin增大,但对于上一组Rmax与Rmin对应的ans已经计算过了,因此不会对答案造成影响;

  注:MAX_W与MIN_W在同一组时只出现①情况;

AC GET☆DAZE

下面是在下的程序,略乱,见谅;

 

技术分享
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #define ll long long
  7 #define MAX_N 1000000039
  8 using namespace std;
  9 struct card
 10 {
 11     ll lw,rw;
 12 };
 13 card num[200039];
 14 ll lmax=-1,rmax=-1,lmin=MAX_N,rmin=MAX_N,rankmax,rankmin,smax,smin=MAX_N,stpmin=MAX_N;
 15 bool cmp(card a,card b)
 16 {
 17     return a.rw<b.rw;
 18 }
 19 void exc(int k)
 20 {
 21     int stp;
 22     stp=num[k].rw;
 23     num[k].rw=num[k].lw;
 24     num[k].lw=stp;
 25 }
 26 int main()
 27 {
 28     ll ans,stp,stpans,n,a,b,c;
 29     scanf("%lld",&n);
 30     for(a=1;a<=n;a++)
 31     {
 32         scanf("%lld%lld",&b,&c);
 33         num[a].lw=max(b,c);
 34         num[a].rw=min(b,c);
 35         if(num[a].lw>=lmax)
 36         {
 37             lmax=num[a].lw;
 38             rankmax=a;
 39         }
 40         if(num[a].rw<=rmin)
 41         {
 42             rmin=num[a].rw;
 43             rankmin=a;
 44         }
 45         lmin=min(lmin,num[a].lw);
 46         rmax=max(rmax,num[a].rw);
 47     }
 48     ans=(lmax-lmin)*(rmax-rmin);
 49     stp=lmax-rmin;
 50     if(rankmax!=rankmin)
 51     {
 52         sort(num+1,num+1+n,cmp);
 53         for(a=1;a<=n;a++)
 54         {
 55             if(num[a].lw==lmax)
 56             {
 57                 rankmax=a;
 58                 break;
 59             }
 60         }
 61         exc(1);
 62         if(num[1].rw<=num[2].rw)
 63         {
 64             smin=num[1].rw;
 65             rankmin=1;
 66         }
 67         else   
 68         {
 69             smin=num[2].rw;
 70             rankmin=2;
 71         }
 72         smax=max(num[1].rw,num[n].rw);
 73         ans=min(ans,stp*(smax-smin));
 74         for(a=2;a<=n;a++)
 75         {
 76             if(a!=rankmax)
 77             {
 78                 exc(a);
 79             }
 80             if(a==rankmin)
 81             {
 82                 if(num[a].rw>num[a+1].rw)
 83                 {
 84                     smin=num[a+1].rw;
 85                     rankmin=a+1;
 86                 }
 87                 else
 88                 {
 89                     smin=num[a].rw;
 90                     rankmin=a;
 91                 }
 92             }
 93             stpmin=min(stpmin,num[a-1].rw);
 94             if(stpmin<=smin)
 95             {
 96                 smin=stpmin;
 97                 rankmin=1;
 98             }
 99             smax=max(smax,num[a].rw);
100             ans=min(ans,stp*(smax-smin));
101         }
102     }
103     printf("%lld",ans);
104     return 0;
105 }
View Code

 

 

 








































以上是关于卡牌分组([AtCoder ARC073]Ball Coloring)的主要内容,如果未能解决你的问题,请参考以下文章

ARC073FMany Moves

Arc073_F Many Moves

「AtCoder AGC002F」Leftmost Ball

[AtCoder][ARC082]Sandglass 题解

AtCoder Grand Contest 002 (AGC002) F - Leftmost Ball 动态规划 排列组合

Atcoder ARC101 E 树dp