Codeforces Global Round 14 D. Phoenix and Socks
作者:互联网
一、算法分析
如何分析这样的题目?
宏观来看,将两只袜子匹配的花费可能是0,1或2,经过分析,先把0花费匹配完之后,不会影响最终结果。那么我们的目标就是使花费2的尽可能地少。
花费0的匹配为:同色不同左右的匹配。
花费1的匹配为:①同色同左右的匹配;②异色不同左右的匹配。
花费2的匹配为:同色同左右的匹配。
在花费0的匹配结束后,每种颜色的袜子就只剩下左袜子或者右袜子。
设第i种左袜子的个数为l[i],右袜子为r[i].在进行完花费0的操作之后:
不妨设左袜子个数l_cnt>=r_cnt,则优先用l_cnt中r_cnt只袜子去换颜色匹配r_cnt,这样最终答案res+=l_cnt-r_cnt;然后就应该只剩下了左袜子。
接着对于左袜子里,某种颜色i的袜子,假设有k只,若k为偶数则可以用花费1的匹配的①情况,否则还剩下的就是花费2的匹配了.
这道题看了好久好久才最后做出来,这启示自己要解出一道题,一定要不断加深对这道题的理解,对题目的理解越深越清晰,则越容易解出来题目。
二、代码
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 using namespace std; 6 const int N=200050<<1; 7 int l[N],r[N]; 8 int n,l_cnt,r_cnt; 9 inline int read() 10 { 11 bool flag=1; 12 int x=0; 13 char c=getchar(); 14 while(c<'0'||c>'9') 15 { 16 if(c=='-') 17 flag=0; 18 c=getchar(); 19 } 20 while(c>='0'&&c<='9') 21 { 22 x=(x<<1)+(x<<3)+c-'0'; 23 c=getchar(); 24 } 25 return (flag?x:~(x-1)); 26 } 27 int res; 28 void prework(){ 29 memset(l,0,sizeof(l)); 30 memset(r,0,sizeof(r)); 31 res=0; 32 } 33 void work(int u,int v,int w[]){ 34 int len=n; 35 int rest=res; //需要转换形状的左袜子 36 for(int i=1;i<=len;i++){ 37 while(rest>0 && w[i]>=2){ //这样写,比写成if的时间复杂度高,但是代码更好理解,有利于之后复习 38 rest--; 39 w[i]-=2; //组内匹配,故减2 40 } 41 } 42 for(int i=1;i<=len;i++){ //组外匹配(和同左边,不同花色的匹配),对应花费为2的匹配 43 while(rest>0 && w[i]>=1){ 44 rest--; 45 w[i]-=1; 46 } 47 } 48 for(int i=1;i<=len;i++) 49 res+=w[i]; 50 } 51 int main(){ 52 53 int T; 54 T=read(); 55 while(T--){ 56 prework(); 57 n=read(),l_cnt=read(),r_cnt=read(); 58 for(int i=1;i<=l_cnt;i++) l[read()]++; 59 for(int i=1;i<=r_cnt;i++) r[read()]++; 60 l_cnt=r_cnt=0; 61 for(int i=1;i<=n;i++){ 62 int minx=min(l[i],r[i]); 63 l[i]-=minx; 64 r[i]-=minx; 65 l_cnt+=l[i]; 66 r_cnt+=r[i]; 67 } 68 69 if(l_cnt>=r_cnt) {res+=l_cnt-r_cnt>>1;work(l_cnt,r_cnt,l);} 70 else {res+=r_cnt-l_cnt>>1;work(r_cnt,l_cnt,r);} 71 printf("%d\n",res); 72 } 73 74 75 return 0; 76 77 }
标签:cnt,匹配,14,Phoenix,花费,res,Global,袜子,include 来源: https://www.cnblogs.com/talk-sea/p/14736456.html