Codeforces Round #616 (Div. 2)
A. Even But Not Even
题意:给定一串数,可在不改变原有数字的顺序下删去任意个数数字,求能否得到数串不能被2整除,但每个数字之和相加可以被2整除。
分析:A题 想了好久 被样例误导 写了好久 冷静下来分析一下数串不能被2整除首先末尾必须是一个奇数,又由于每个数字之和相加可以被2整除且末尾已经有一个奇数了这就需要再来一个奇数与末尾的奇数相加拼成偶数满足条件,故我们得到 至少需要两个奇数,中间可以有任意偶数。
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int N =3010; char s[N]; int t,n; int main() { scanf("%d",&t); while(t--) { scanf("%d",&n); scanf("%s",s+1); int a=-1,b=-1; int len=strlen(s+1); for(int i=1;i<=len;i++) { if((s[i]-'0')&1) { if(a==-1) a=i; else{ b=i; break; } } } if(a!=-1&&b!=-1) { for(int i=a;i<=b;i++) { printf("%c",s[i]); } printf("\n"); } else { printf("-1\n"); } } return 0; }
B. Array Sharpening
题意:有t组数,每组数有n个数字,若数字不为0,可以对其进行减1操作,可进行多次,最后判断是否存在某个位置k(1<=k<=n),使得a1<a2<…ak+1>…>an。
分析:其实就是说,一个数组,都是非负整数,只要a[i]不是0,你就可以对他进行任意次数的-1操作,也就是他可以变成0~a[i]中的任何一个值。然后问对这个数组进行操作后,能不能分为单调上升和单调下降两个部分。经过思考后我们可以发现一些其中的规律 如果a[1]=0 那么必定是不成立的 因为单调上升 若a【1】=0那a[0]最小也只能是0了,两个0挨着显然不满足条件。
其实这样规律就出来了 即a[i]>=i;右边同理 a[i]>=n-i-1
这样的话本题目就十分的简单了 我们分别从数组两边扫描 记录第一个不满足上述关系的点 然后这两个点若有交集 就成立 代表交集内的点都可以做峰值k
#include <stdio.h> #define N 1001000 int t,n,l,r; int s[N]; int main() { scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&s[i]); for(int i=0;i<n;i++) { if(s[i]>=i) l=i; else break; } for(int i=n-1;i>=0;i--) { if(s[i]>=n-i-1) r=i; else break; } if(l>=r) printf("Yes\n"); else printf("No\n"); } }
C. Mind Control
题意:有一个由n个数组成的序列,然后恰有n个人进行排队,每个人只能从两端进行取数。你排在第m位,你可以控制k个人取特定的数字(前或后),你取的时候会取最优的,问你取的数的最小值最大是多少。
分析:题意有一点绕啊 数的最小值的最大值
真正开始分析:我们站在第m个位置,控制的人都要在我们位置的前面才可能对结果产生影响,我们最多能控制k个人,当然贪心可得控制的人越多对我们的结果越有利。故我们实际控制的有效人数应该是k=min(k,m-1),我们也可以算出不能控制的人数m-1-k然后分别枚举 他们有多少个人选了首位多少个人选了末尾 然后分别表示他们选完后的 首位和末位比较求最值
#include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int INF=0x3f3f3f3f; int a[3550]; int main() { int t,n,m,k; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); k=min(k,m-1);//实际有效的控制人数 int ans=0; int res=m-1-k;//不能控制的人数 for(int i=0;i<=k;i++){//i为能控制得人选首位元素的个数 int x=INF;//求最大值先设一个无穷大量 for(int j=0;j<=res;j++){//j不能控制的人数选首位元素的个数 int l=a[j+i+1];//到“我”选时数组中的首位元素 int r=a[n-(k-i+res-j)]; x=min(x,max(l,r));//求最小值 } ans=max(ans,x);//求最小值的最大值 } printf("%d\n",ans); } return 0; }