链接: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;
}

京公网安备 11010502036488号