Codeforces Round #200 (Div. 2) 题解
A. Magnets
题意:给你一列按照顺序的磁铁0代表负极,1代表正极,询问你这些磁铁是几组极性相反的磁铁可以连接在一起变成一组
思路:按照字符串把这些磁铁都读入,然后用一个ans变量记录最后的答案,最少有一组,如果当前的一小块磁铁与上一块不同,ans++,因为他们肯定不能连接在一起,同极排斥,相同就接在一起
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+7; string a[maxn]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++){ cin>>a[i]; } int ans=1; for(int i=2;i<=n;i++){ if(a[i]==a[i-1])continue; ans++; } cout<<ans<<endl; return 0; }
B. Simple Molecules
题意:给你123号点的度数,询问你这三个点中是怎么连接的,可以有重边,但是不允许有自环。让你打印12,23,31中有几条边
思路:因为数据范围是1e6,直接枚举12中间有多少边,根据12之间边的数量推出其他边的数量,最后check一下
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; int main() { int a,b,c; scanf("%d%d%d",&a,&b,&c); int maxe=max(a,max(b,c)); for(int i=0;i<=maxe;i++){ int as=i,qw=b-i,zx=c-qw; if(a==as+zx&&as>=0&&qw>=0&&zx>=0){ printf("%d %d %d\n",as,qw,zx); return 0; } } puts("Impossible"); return 0; }
C. Rational Resistance
题意:给你许多电阻大小为1的电阻,你可以进行串联或者并联,按照物理上的串并联法则,输入nm,询问你用电阻大小为1的电阻构成总电阻为n/m最小需要多少个
思路:大于一的部分肯定是串联得到的,因为并联会使总电阻减小,所以在大于一的部分我们用串联的电阻最优,然后考虑小于一的部分只能有并联电阻以后再和之前的部分串起来,并联的时候会交换nm,然后就一直这样向下贪心
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long LL; int main() { LL n,m; cin>>n>>m; LL ans=0; while(n!=1){ ans+=n/m; n%=m; if(n==0)break; swap(n,m); } if(n==1)ans+=m; cout<<ans<<endl; return 0; }
D. Alternating Current
题意:有两条电线缠在一起,上面的线是+,下面的是-,这两根线缠在一起,+-线相交的地方,如果+线在上面,就输入+,-线在上面就输入-,问你能否将两根缠着的线解开
思路:我们可以发现读入的字符串中如果有两个相同的字母,并且这两个字母相邻。我们就可以把这连个相交的线解开,解开后新的相邻字母相同仍然可以解开,样例:-++-,先解开中间的++,然后字符串变为--,在解开即可,然后就变成了括号匹配的过程,看最后的栈中是否为空即可,为空表示全部解开,非空表示没有解开
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+7; char a[maxn]; char stk[maxn]; int top=0; int main() { scanf("%s",a+1); int len=strlen(a+1); stk[++top]=a[1]; for(int i=2;i<=len;i++){ if(a[i]==stk[top]){ top--; } else stk[++top]=a[i]; } if(top==0)puts("Yes"); else puts("No"); return 0; }
E. Read Time
题意:给你n个磁头,m个磁区,每个磁头在每一秒可以选择向左移动一格或者向右移动一格或者留在原地,问你最少需要多少时间似的每个磁区都被磁头走过
思路:二分答案,对于二分的时间mid,保证左侧的磁区都被覆盖到后尽可能的向右移动,这样一直贪心,最后检查是否所有的磁区都被覆盖到
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=1e5+7; LL a[maxn],b[maxn]; int n,m; bool check(LL x) { int now=1; for(int i=1;i<=n;i++){ LL dis=0; if(b[now]>=a[i]){ dis=x; } else{ if(b[now]+x<a[i])return false; dis=x-2LL*(a[i]-b[now]); dis=max(dis,(x-a[i]+b[now])/2); } dis+=a[i]; while(b[now]<=dis)now++; if(now>m)break; } if(now>m)return true; return false; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); } for(int i=1;i<=m;i++){ scanf("%lld",&b[i]); } LL L=0,R=2e13; LL ans=0; while(L<=R){ LL mid=(L+R)>>1; if(check(mid)){ R=mid-1; ans=mid; } else { L=mid+1; } } printf("%lld\n",ans); return 0; }