Educational Codeforces Round 78 (Rated for Div. 2) --补题



链接

直接用数组记录每个字母的个数即可

#include<bits/stdc++.h>

using namespace std;

int a[26] = {0};
int b[26] = {0};

int judge()
{
	//cout<<"111"<<endl;
	for (int i = 0; i < 26; ++i)
	{
		if (a[i]!=b[i])
		{
			return 0;
		}
	}
	return 1;
}
int main()
{
	//ios::sync_with_stdio(false);
	int t;
	cin>>t;
	char p1[101],p2[101];
	int flag = 0;
	while(t--)
	{
		cin>>p1;
		cin>>p2;
		flag = 0;
		memset(a, 0, sizeof(a));
		memset(b, 0, sizeof(b));
		int len = strlen(p1);
		if (len >strlen(p2))
		{
			cout<<"NO"<<endl;
			continue;
		}
		else
		{
			for (int i = 0; i < len; ++i) //先算出一个值
			{
				a[p1[i]-'a'] ++;
				b[p2[i]-'a'] ++;
			}
			
			for (int i = 0; i<(strlen(p2)-strlen(p1)); ++i)
			{
				// for (int i = 0; i < 26; ++i)
				// {
				// cout<<b[i]<<endl;
				// }
				if(judge())
				{
					flag = 1;
					break;
					//cout<<"111"<<endl;
				}
				else{
					b[p2[i]-'a'] -= 1;
					b[p2[i+len]-'a'] += 1;
					//cout<<p2[i]<<endl;
				}
				
			}
		
		}
		if (judge())
		{
			flag = 1;
		}
		if (flag)
			{
				cout<<"YES"<<endl;
			}
		else
			cout<<"NO"<<endl;
	}

	return 0;
}



链接

一直给小的数加,直到大于等于大的那个数,这个时候就可能出现这种情况
1. 超过了一个偶数(0也算)
2. 超过了一个奇数,当前加到的数是奇数
3. 超过了一个奇数,当前加的是偶数
分析可以发现,如果超过了一个偶数,肯定可以从前面加的数里面取这个数的一半的那个数来调平。所以次数就是i
但是如果超过的是奇数,那么是不可能调平的,因为奇数不可能分解成相等的整数(可以思考一下,我们只需要调平超出的数就行)
所以分析可知,必须使得超出的数是偶数,那么此时如果i是奇数,结果就是i+2, i是偶数结果就是i+1

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main () {
 
	int t;
	cin >> t;
	while(t--){
		ll a,b;
		cin >> a >> b;
		if(a < b) {
			swap(a, b);
		}
		ll c = a - b;
		int i = 0;
		ll s = 0;
		if(c==0)
		{
			cout<<0<<endl;
			continue;
		}
		while(1){
			i++;
			s = i * (i + 1) / 2;
			if(s < c) {
				continue;
			}
			else
			{
				if((s-c)&1)
				{
					if(i&1)
					{
						cout<<i+2<<endl;
						break;
					}
					else
					{
						cout<<i+1<<endl;
						break;
					}
				}
				else
				{
					cout<<i<<endl;
					break;
				}
			}
		}
	}
 
}



链接

分前半段和后半段求前缀和,对前半段预处理后。遍历后半段的去找最小值。
#include<bits/stdc++.h>

using namespace std;

int a[200000];
int b[400000];
int vis[400000];

int main(int argc, char const *argv[])
{
	int t;
	ios::sync_with_stdio(false);
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		memset(b, 0x3f, sizeof(b));
		memset(vis,0,sizeof(vis));
		int count = 0;
		for (int i = 1; i<=n; ++i)
		{
			cin>>a[i];
			a[i] = a[i]==2? -1:1;
			count += a[i];
		} //记录下来了
		a[n+1] = 0;
		b[200000] = 0;
		vis[200000] = 1;
		for (int i = n; i >=1; --i) //前缀和,前半部分是要倒着求得
		{
			a[i] += a[i+1];
			if(!vis[200000+a[i]]) //记录下到达每个位置的最近的放步数
			{
				vis[200000+a[i]] = 1;
				//cout<<200000+a[i]<<" "<<n-i+1<<endl;
				b[200000+a[i]] = n-i+1; //给他赋值,记录最快速到达的放法
			}
		}
		a[0] = 0;
		for (int i = 1; i <= n; ++i)
		{
			cin>>a[i];
			a[i] = a[i] == 2? -1:1;
			count += a[i];
			a[i] += a[i-1]; //后半部分正着求前缀和
		}
		int mi = b[200000+count]; //表示全部从左边取
		for (int i = 1; i <= n; ++i)
		{
			//cout<<mi<<endl;
			mi = min(mi, b[count-a[i]+200000]+i);
		}
		if (count)
		{
			cout<<mi<<endl;
		}
		else
		{
			cout<<0<<endl;
		}
	}
	return 0;
}
posted @ 2019-12-20 17:46  CrosseaLL  阅读(139)  评论(0编辑  收藏  举报