链接:https://codeforces.com/contest/1496
最后几分钟把D交了 然后分享跟实验室的人 打完一看rank500+ 差三分1500的我应该能上波大分吧 结果。。。凌晨一点登上cf一看 你收到一封邮件。。。被查重skipped
A:
题意:给你一长度为n的字符串s和一个k,求在s的基础上能否求出一个长度为2*k+1的字符串t,且t满足a1+a2+...+ak+ak+1+R(ak)+...+R(a2)+R(a1),R(ai)代表是ai的反串
思路:从两边开始判断有多少个相等的字符 如果个数大于等于k则可以
代码:
while(T--) { int n=read(),k=read(); scanf("%s",a+1);int cnt=0; for(int i=1;i<=n/2;i++) { if(a[i]==a[n-i+1])cnt++; else break; } if(cnt>=k&&(cnt*2!=n||cnt>k))puts("YES"); else puts("NO"); }B:
题意:给你一个序列 mex代表序列中第一个大于等于0且没出现的数a,max代表序列中的最大数b 每次操作增加一个(a+b)/2 向上取整的数 问最后有多少个不同的数
思路:规律 当(a+b)/2=a 那么讲一直添加新的数下去 最后结果就是n+k。如果不等那就最多只能增加一个数 且还要判断这个新加的数是否之前存在 存在答案就为n 否则答案为n+1。我是二分去找这个数
代码:
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--) { int n,k; cin >> n >> k; vector<int>v; for(int i=1;i<=n;i++) { int x; cin >> x; v.push_back(x); } sort(v.begin(),v.end()); int maxn=v[n-1]; int tmp=0; if(k==0) { cout << n << endl; continue; } for(auto i : v) { if(i==tmp) { tmp++; } } //cout << tmp << endl; int ans= (int)ceil(1.0*(tmp+maxn)/2); //cout << ans << endl << endl; int p = lower_bound(v.begin(),v.end(),tmp)-v.begin(); //cout << p << endl; if(v[p]==tmp||(p+1)>n) cout << n+k << endl; else { int p = lower_bound(v.begin(),v.end(),ans)-v.begin(); //cout << p <<endl; if(v[p]==ans) cout << n << endl; else cout << n+1 << endl; } } return 0; }C:
题意:就是x轴和y轴上点的距离和最小是多少。每个点只能配对一次。
思路:我没想太多 就两个坐标轴上最小的点互相匹配就行,开始一直tle4 把输入的数据类型从double改int就过了
代码:
D :
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--) { int n; cin >> n; vector<double>x,y; for(int i=1;i<=2*n;i++) { int xx,yy; cin >> xx >> yy;//这里别用double if(xx==00) y.push_back(fabs(yy)); else x.push_back(fabs(xx)); } sort(x.begin(),x.end()); sort(y.begin(),y.end()); double ans=0; for(int i=0;i<x.size();i++) { ans+=sqrt(x[i]*x[i]+y[i]*y[i]); } printf("%.14lf\n",ans); } return 0; }
D :
题意:两个人走路 先手的那个人只能移动到相邻的位置且同时该值要小于移动前的值且后走的那个人不能在这,后手只能移动到相邻的位置同时该值要大于移动前的值并且先走的那个人不能在移动后的位置。并且后手知道前手第一步的位置
思路:慢慢分析:
不难看出,每个人都是走一条单调序列,且最优情况下就是这条单调序列要最长。分情况讨论:
1.当只有一条最长单调序列,先手必输(先手用a表示 后手用b),无论a选哪个位置,b只要选的位置与a所在的位置构成一条长度为偶数的单调序列那么a将无路可走。
2.当有多条(大于3)的单调序列,a必输,因为多条长度相等,先走的人将无路可走
3.当有两条且不相交时,a必输,因为b可以直接选另外一条。当相交时又是两种情况一是形状像一个V和倒过来的V。先分析倒V,a肯定选山顶,那么b选山底的话如果长度为奇数,a赢,否则b赢;如果b不选山底,那a往b的反方向走那么a走的长a赢。
在分析正V,a最优肯定选两端,但b只要从山底往另一个方向走,那a必输。
分析完毕。
代码:
#include <iostream> #include <cstring> #include <algorithm> #include <set> typedef long long ll; using namespace std; const int N = 1e5+5; int a[N],l[N],r[N]; int main() { int n; cin >> n; for(int i=0;i<n;i++) { cin >> a[i]; l[i]=1,r[i]=1; } int maxn=0;//找序列的最大值 for(int i=1;i<n;i++) { if(a[i]>a[i-1]) { l[i]=l[i-1]+1;//确定每一条单调递增序列的长度 maxn=max(maxn,l[i]);//最长单调序列的长度 } } for(int i=n-2;i>=0;--i) { if(a[i+1]<a[i]) { r[i]=r[i+1]+1;//确定每一条单调递减序列的长度 maxn=max(maxn,r[i]); } } int cnt=0,flag=0;//cnt有几条最长单调序列 ,flag当不同的单调序列相交且相交点的值为整个序列的最大值 for(int i=0;i<n;i++) { if(l[i]==r[i]&&l[i]==maxn)//当两条单调序列相交,且交点为单调序列长度的最大值 { flag++;//标记一下,因为这是a能赢的条件之一 } if(l[i]==maxn) cnt++; if(r[i]==maxn) cnt++; } if(flag==1&&cnt==2)//最长的单调序列条数为2 且两条序列相交 { if(maxn&1) //长度为奇数 { cout << "1"<< endl; } else { cout << "0" << endl; } } else cout << "0" << endl; return 0; }