卡牌分组([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 }
以上是关于卡牌分组([AtCoder ARC073]Ball Coloring)的主要内容,如果未能解决你的问题,请参考以下文章
「AtCoder AGC002F」Leftmost Ball
AtCoder Grand Contest 002 (AGC002) F - Leftmost Ball 动态规划 排列组合