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