http://codeforces.com/contest/676
A. Nicholas and Permutation
题意:有一个从1到n的数列,可以任意对调两个数字一次,问数字1和n所在位置之间的最大距离是多少?
思路:可以选择把数字1和开头的数字对调,或者1和末尾的数字对调,或者n和开头的数字对调,或者n和末尾的数字对调,一共四种对调方法,只需要比较对调之后的下标差的绝对值,取最大的即可。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int main() { int n,a,maxa=0,mina=105,maxid=0,minid=0; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a); if(a>maxa) { maxa=a; maxid=i; } if(a<mina) { mina=a; minid=i; } } int res=max(abs(n-minid),abs(minid-1)); res=max(res,max(abs(n-maxid),abs(maxid-1))); printf("%d ",res); return 0; }
B. Pyramid of Glasses
题意:如下图,倒酒,共有n层,在时间t秒后,问有几个酒杯是满的?
思路:每秒每个满的酒杯都能分别流下一半到下一层的对应左右两个酒杯中,那么可以开一个二维数组a[i][j],初始化为0,a[1][1]=t; 然后遍历每个酒杯,如果a[i][j]>=1,即是满的酒杯,那么ans++,然后把剩下的酒(其实就是时间t)分给下一层对应的两个酒杯a[i+1][j],a[i+1][j+1]。
注意:数组a必须是double类型的
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int main() { int n,t; double a[15][15]; memset(a,0,sizeof(a)); scanf("%d %d",&n,&t); a[1][1]=t; int ans=0; for(int i=1;i<=n;i++) { for(int j=1;j<=i;j++) { if(a[i][j]>=1) { ans++; a[i+1][j]+=(a[i][j]-1)/2; a[i+1][j+1]+=(a[i][j]-1)/2; } } } printf("%d ",ans); return 0; }
C. Vasya and String
借鉴:http://www.voidcn.com/blog/tc_to_top/article/p-5986745.html
题意:一个字符串只包含a和b,可以改变其中k个,求最大的美丽值,美丽值定义为子串中所含字符均相同的的最长子串的长度。
思路:对于k次操作,要么全换a要么全换b,对这两种情况取最大即可,算的时候用两点法,r向右直到k用完,然后l从左开始加,不断还原k值。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; char s[100005]; int n,k; int op(char c) { int l=0,r=0; int ans=0,cnt=0; while(l<n&&r<n) { while(((s[r]==c)||cnt<k)&&r<n) { if(s[r]!=c) cnt++; r++; } ans=max(ans,r-l); while(s[l]==c&&l<=r) l++; l++; cnt--; } return ans; } int main() { scanf("%d %d",&n,&k); scanf("%s",s); printf("%d ",max(op('a'),op('b'))); return 0; }