算法训练
Posted kasenbob
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法训练相关的知识,希望对你有一定的参考价值。
1.gym 101755A
a=c?g,b=d?g,s=a+b=(c+d)?g 故若g%s==0且s>g则a=g,b=s?g显然符合条件,否则无解
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; typedef pair<int,int>P; const int INF=0x3f3f3f3f,maxn=100001; int main() { int s,g; while(~scanf("%d%d",&s,&g)) if(s%g!=0||s==g)printf("-1 "); else printf("%d %d ",g,s-g); return 0; }
2.gym- 101755B
显然组成三角形面积最小时三个顶点应该是相邻的三个点,求出这nn个由相邻三个顶点组成的三角形面积维护最小值即为答案
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; typedef pair<int,int>P; const int INF=0x3f3f3f3f,maxn=200005; int n,x[maxn],y[maxn]; ll S(int x0,int y0,int x1,int y1) { return abs((ll)x0*y1-(ll)x1*y0); } int main() { while(~scanf("%d",&n)) { for(int i=0;i<n;i++)scanf("%d%d",&x[i],&y[i]); x[n]=x[0],y[n]=y[0]; x[n+1]=x[1],y[n+1]=y[1]; ll ans=4e18+5; for(int i=0;i<n;i++) ans=min(ans,S(x[i+1]-x[i],y[i+1]-y[i],x[i+2]-x[i],y[i+2]-y[i])); printf("%I64d ",ans); } return 0; }
3.gym 101755C
把所有区间按右端点升序排,右端点相同则按左端点升序排,每次买第一个区间的右端点即可,这样后面的区间只要左端点不超过该右端点就都不用买
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; const int INF=0x3f3f3f3f,maxn=200005; int n,ans[maxn],res; struct node { int id,l,r; bool operator<(const node &b)const { if(r!=b.r)return r<b.r; return l<b.l; } }a[maxn]; int main() { while(~scanf("%d",&n)) { for(int i=0;i<n;i++)scanf("%d%d",&a[i].l,&a[i].r),a[i].id=i+1; sort(a,a+n); res=0; ans[res++]=a[0].r; for(int i=1;i<n;i++) if(a[i].l<=ans[res-1])continue; else ans[res++]=a[i].r; printf("%d ",res); for(int i=0;i<res;i++)printf("%d%c",ans[i],i==res-1?‘ ‘:‘ ‘); } return 0; }
4.gym 101755E
只需要找到需要比较的区间L,R,在这个区间内比较一下是否为相反的子串,就可以了。
#include <cstdio> #include <string> #include<cstring> using namespace std; int main() { char s[200005]; char t[200005]; while(~scanf("%s %s",&s,&t)) { int n = strlen(s); int l = 0, r = n; for(int i = 0; i < n; i ++) { if(s[i] == t[i]) l++; else break; } for(int i = n; i >= 0; i --) { if(s[i]== t[i]) r --; else break; } //cout << l << " " << r << endl; int f = 0; for(int i = l; i <= r; i ++) { if(s[i] != t[r + l - i]) { f= 1; break; } } if(f==0)printf("YES "); else printf("NO "); } return 0; }
5.gym 101755J
统计每个长度出现的次数numinumi,答案即为?∑?numi2?2?
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; typedef pair<int,int>P; const int INF=0x3f3f3f3f,maxn=200001; int n,a[maxn]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int temp; scanf("%d",&temp); a[temp]++; } int ans=0; for(int i=1;i<=200000;i++)ans+=a[i]/2; printf("%d ",ans/2); return 0; }
6.gym 101755L
由于只是判断tt是否为ss的子序列,故贪心的用尽可能ss串靠前的字符取匹配tt,以Nex[i][j]Nex[i][j]表示ss串的第ii个字符后面第jj个字母第一次出现的位置,在匹配过程中记录tt串的每个字符在ss串中的对应匹配位置,每次加入新字符jj时,考虑之前tt串的最后一个字符在ss串的匹配位置ii,如果next[i][j]next[i][j]有合法值那么说明tt依旧是ss的子序列,否则不是
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; typedef pair<int,int>P; const int INF=0x3f3f3f3f,maxn=200005; int n,q,Next[maxn][26],pos[26],ans[maxn]; char s[maxn],op[10]; int main() { scanf("%s",s+1); n=strlen(s+1); memset(Next,-1,sizeof(Next)); memset(pos,-1,sizeof(pos)); for(int i=n;i>=0;i--) { for(int j=0;j<26;j++)Next[i][j]=pos[j]; pos[s[i]-‘a‘]=i; } scanf("%d",&q); int m=0,len=0; ans[0]=0; while(q--) { scanf("%s",op); if(op[1]==‘u‘) { scanf("%s",op); if(ans[m]!=-1&&Next[ans[m]][op[0]-‘a‘]!=-1)ans[m+1]=Next[ans[m]][op[0]-‘a‘],m++,len++; else ans[++m]=-1; } else m--,len=min(len,m); if(len==m)printf("YES "); else printf("NO "); } return 0; }
7.gym 101755M
由于每个串和ss至多差一个字符,那么aa和b,cb,c分别至多差两个字符,找出aa字符串与b,cb,c字符串不同的位置,显然不同的位置数不超过33个,否则无解,首先判断aa本身是不是合法解,然后枚举这三个位置中的一个为aa和ss相异的位置,然后枚举该位置的字符判断是否有解,统计解的数量即可
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; typedef pair<int,int>P; const int INF=0x3f3f3f3f,maxn=200005; char s[3][maxn]; int n,vis[maxn]; bool check() { for(int i=1;i<=2;i++) { int num=0; for(int j=0;j<n;j++) if(s[0][j]!=s[i][j]) { num++; if(num>1)return 0; } } return 1; } int main() { for(int i=0;i<3;i++)scanf("%s",s[i]); n=strlen(s[0]); int m=0,flag=1,pos[10]; for(int i=1;i<=2;i++) { for(int j=0;j<n;j++) if(s[0][j]!=s[i][j])vis[j]=1; } for(int i=0;i<n;i++) if(vis[i]) { pos[m++]=i; if(m>4)break; } if(m>3)flag=0; int ans=0,anspos; char ansc; if(flag) { if(check())ans++,anspos=0,ansc=s[0][0]; for(int i=0;i<m;i++) { char t=s[0][pos[i]]; for(int j=0;j<26;j++) if(‘a‘+j!=t) { s[0][pos[i]]=‘a‘+j; if(check())ans++,anspos=pos[i],ansc=j+‘a‘; } s[0][pos[i]]=t; } if(ans==0&&m)flag=0; if(m==0)ans=2; } if(!flag)printf("Impossible "); else if(ans>1)printf("Ambiguous "); else { s[0][anspos]=ansc; printf("%s ",s[0]); } return 0; }
以上是关于算法训练的主要内容,如果未能解决你的问题,请参考以下文章
有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]
片段(Java) | 机试题+算法思路+考点+代码解析 2023