https://codeforces.com/contest/1649/problem/A
最多只能跳一次,从第一个0的前一个位置跳到最后一个0的下一个位置,循环找出位置后处理即可
#include<bits/stdc++.h> #define ll long long using namespace std; const int N =100005; int n,t; int a[105]; string s; int main(){ cin>>t; while(t--){ cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } int ans=0; int l=0,r=0; ///1 for(int i=1;i<=n;i++){ if(a[i]==0){ l=i-1; break; } } for(int i=n;i>=1;i--){ if(a[i]==0){ r=i+1; break; } } if(l>=r) ans=0; else ans=r-l; cout<<ans<<endl; } return 0; }
https://codeforces.com/contest/1649/problem/B
样例要稍微认真看看,思路为贪心。
#include<bits/stdc++.h> #define ll long long using namespace std; const int N =100005; int n,t; int a[N]; string s; int main(){ cin>>t; while(t--){ cin>>n; ll s=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); s+=a[i]; } if(s==0){ puts("0"); continue; } sort(a+1,a+n+1); if(a[n]>s-a[n]+1){ cout<<a[n]-(s-a[n])<<endl; } else puts("1"); } return 0; }
https://codeforces.com/contest/1649/problem/C
思路很好想:由曼哈顿距离的定义,我们可以分开考虑相同颜色的点的横纵坐标,先用一个数据结构存一下每个点的颜色、横纵坐标,然后把点对间的贡献算进答案。
那么要怎么算呢?
我首先没有分析时间复杂度,写了一个O(color.size()*cord.size()^2)的做法,就是统计每种颜色下每个位置的点的个数,结果超时了
倒是想复杂了,可以O(cord.size())求出不同颜色的点的横(纵)坐标,排序后,利用类似前缀和的思想跑一趟循环,即可求出答案
#include<bits/stdc++.h> #define ll long long using namespace std; const int N =100005; int n,t,x,m; set<int>color; vector<int>row[N],col[N]; ///col/row[color]={pos,cnt} vector<pair<int,int>>r; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&x); if(color.count(x)==0) color.insert(x); row[x].push_back(i); col[x].push_back(j); } } ll ans=0; for(auto i=color.begin();i!=color.end();i++){ sort(row[*i].begin(),row[*i].end());// for(int j=0;j<row[*i].size();j++){ ans+=1ll*row[*i][j]*j-row[*i][j]*(row[*i].size()-j-1); } sort(col[*i].begin(),col[*i].end()); for(int j=0;j<col[*i].size();j++){ ans+=1ll*col[*i][j]*j-col[*i][j]*(col[*i].size()-j-1); } } printf("%lld\n",ans); return 0; }
https://codeforces.com/contest/1649/problem/D
可以O(clogc)求解。
先给数组排序,对于每一个位于[1,c]区间的数i,枚举它的倍数j,先在数组中找有没有位于[i,i+j)范围内的数,如果有,那么j/i也必须存在,否则不满足条件 这样判断
#include<bits/stdc++.h> #define ll long long using namespace std; const int N =1000005; int n,t,c; int a[N]; //map<int,int>vis; bool vis[N]; bool check(){ if(vis[1]==0){ return 0; } for(int i=1;i<=c;i++){ if(vis[i]==0) continue; for(int j=2*i;j<=c;j+=i){ int ind=lower_bound(a+1,a+n+1,j)-a; if(ind<=n&&a[ind]<j+i){ if(!vis[j/i]){ return 0; } } } } return 1; } int main(){ scanf("%d",&t); while(t--){ scanf("%d%d",&n,&c); for(int i=1;i<=c;i++) vis[i]=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); vis[a[i]]=1; } sort(a+1,a+n+1); if(check()==1) puts("Yes"); else puts("No"); } return 0; }
注意一下能用数组就不要用map存!!本题就会超时的
又好久没打cf,A题一上来wa了一发,罚时++;B题竟然因为数组范围写错fst了。。。C题这样的题见少了,类似前缀和思想,tle了;D有思路做不对,emmm还是题目写少了吧,细节注意的不够
cf平时还是要多打打,可以练习思维,也提高了debug能力。
目标:每天一套div2练习!!一定要留下来啊!!!