链接:https://codeforces.com/contest/1473
A:水题。先排序,比较最小两个数的和与d的大小关系,再判断下最大值与d的大小关系即可。
#include <iostream> #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; int st[10005],prime[10005],cnt; int vis[105]; ll a[200005]; void ola() { for(int i=2;i<=1000000;i++) { if(st[i]==0) prime[cnt++]=i; for(int j=0;j<=cnt&&j*prime[i]<=1000000;j++) { st[i*prime[j]]=1; if(i%prime[j]==0) break; } } } ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } ll qpow(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans % mod; } int main() { ios::sync_with_stdio; cin.tie(0);cout.tie(0); int t; cin >> t; while(t--) { int n,d; cin >> n >> d; for(int i=1;i<=n;i++) cin >> a[i]; sort(a+1,a+1+n); int minn=a[1]+a[2]; if(a[1]+a[2]<=d||a[n]<=d) cout<< "YES" << endl; else cout << "NO" << endl; } return 0; }
B: 这题卡了我好久。。。想复杂了,不然这场也能上波大分。题意就是给你两个字符串s,t,问你能不能得到一个长度为s和t长度的最小公倍数且能被s和t整除的字符串。只需要求出最小公倍数,让s和t自行累加直到长度为最小公倍数即可,然后判断二者是否相等。
#include <bits/stdc++.h> using namespace std; int sum[200005],ul[200005],dl[200005],ur[200005],dr[200005]; int main() { ios::sync_with_stdio; cin.tie(0);cout.tie(0); int q; cin >> q; while(q--) { string s,t; cin >> s >> t; int ls=s.length(),lt=t.length(); int tmp=ls*lt/__gcd(ls,lt); string s1,s2; for(int i=1;i<=tmp/ls;i++) s1+=s; for(int i=1;i<=tmp/lt;i++) s2+=t; //cout << s1 << s2 << endl; if(s1==s2) cout << s1 << endl; else cout << -1 << endl; } return 0; }C:输入两个数n,k,数组a元素为1~k和k-1~2*k-n。输出一个数组p,并且使b[i]=p[a[i]],且b中逆序数的个数不能大于a中的个数,同时b要字典序最大。由题意可以知道a中逆序数只存在k~(2*k-n),那么既然b[i]的逆序数与a[i]相同,也就是说直到b[i] = k-(n-k)都是相同的,作用在p上就是i = 2*k-n前,在这之前p[i]正序递增。 为了让b[i]的字典序大于a[i],在b[i] = k-(n-k)后只要让他和a[i]的顺序相反即可(a是先正后逆,b就先逆后正,由于大数在先故b的字典序一定大于a)。
int main() { ios::sync_with_stdio; cin.tie(0); cout.tie(0); int t; cin >> t; while(t--) { int n,k; cin >> n >> k; if(n<=k) { cout << "1"; for (int i = 2; i <= k; i++)cout << " " << i; cout << endl; } else { int tmp=2*k; for (int i = 1; i < tmp - n; i++) { cout << i << " "; } for (int i = k; i >= tmp - n; i--) { cout << i << " "; } cout << endl; } } return 0; }
D:读了题之后觉得就是线段树,好久没写线段树有点不熟练了,又不想重新去翻看以前写的关于线段树博客,就没做了(而且比赛期间读了假题,已知以为是要我们求区间【l,r】)。打完看了别人的代码,直呼好家伙。
思路:前缀和然后枚举当前最大值和最小值 ,在逆序模拟一边求最大值和最小值,最后答案就是求【0,l-1】和【r+1,n】的最大值与最小值之差+1(最开始有一个0)。之后花时间用线段树把这道题再做一遍
int main() { ios::sync_with_stdio; cin.tie(0);cout.tie(0); int t; cin >> t; while(t--) { int n,m; cin >> n >> m; scanf("%s",s+1); memset(sum,0,sizeof(sum)); memset(ul,0,sizeof(ul)); memset(dl,0,sizeof(dl)); memset(ur,0,sizeof(ur)); memset(dr,0,sizeof(dr)); for(int i=1;i<=n;i++) { if(s[i]=='+') sum[i]=sum[i-1]+1; else sum[i]=sum[i-1]-1; ul[i]=max(ul[i-1],sum[i]); dl[i]=min(dl[i-1],sum[i]); } dr[n+1]=0,ur[n+1]=0; for(int i=n;i>0;i--) { if(s[i]=='+') ur[i]=ur[i+1]+1,dr[i]=dr[i+1]+1; else dr[i]=dr[i+1]-1,ur[i]=ur[i+1]-1; ur[i]=max(0,ur[i]); dr[i]=min(0,dr[i]); } for(int i=1;i<=m;i++) { int l,r; cin >> l >> r; int ans=max(ul[l-1],sum[l-1]+ur[r+1])-min(dl[l-1],sum[l-1]+dr[r+1])+1; cout << ans << endl << endl; } } return 0; }