Codeforces Round 1023 (Div. 2) ABC

链接 

Dashboard - Codeforces Round 1023 (Div. 2) - Codeforces

A

将数组a分成两组,使得gcd(b) != gcd(c)

思路

gcd(a,b) <= min(a,b)

求数组a的max,min

如果数组a都一样无解 (即max == min

否则有解:让是max的一组,不是max的放另一组

代码

粘一下题解的吧

#include <bits/stdc++.h>
using namespace std;

int main(){
    int t; cin >> t;
    
    while (t--){
        int n; cin >> n;
        vector <int> a(n);
        for (int i = 0; i < n; i++){
            cin >> a[i];
        }
        int mn = *min_element(a.begin(), a.end());
        int mx = *max_element(a.begin(), a.end());
        if (mn == mx){
            cout << "No\n";
            continue;
        }
        cout << "Yes\n";
        for (int i = 0; i < n; i++){
            cout << (1 + (a[i] == mx)) << " \n"[i + 1 == n];
        }
    }
    return 0;
}

B 博弈+思维

思路

要满足max - min <= k,最优的就是取最大的减,tom先max --,再计算max - min,如果 > k,tom一开始就输了,

只要tom第一次能操作,则jeryy一定不会出现max - min > k( jerry也同样取max--),这样下来,输的情况就只有数组全为0;每次操作只会-1,只要计算sum,奇数tom赢,偶数Jerry赢

代码

void solve()
{

	cin >> n >> k;
	LL sum = 0;
	for (int i = 1;i <= n;i ++) 
	{
		cin >> a[i];
		sum += a[i];
	}
	
	sort(a + 1,a + 1 + n);
	a[n] --;
	sort(a + 1,a + 1 + n);
	
	if (a[n] - a[1] > k) cout << "Jerry" << endl;
	else 
	{
		if (sum & 1) cout << "Tom" << endl;
		else cout << "Jerry" << endl;
	}
	
	
}

 

C 最大字段和+构造

思路

1.先求出每一段已知的a[i]的和sum,如果存在一段和>k,无解

                                                        如果存在sum == k,标记存在

2.如果a数组全为已知,且存在最大字段和 == k,有解;否则无解

3.此时每一段的sum都 <= k,且存在未知的a[i];找一个未知的a[i],将其置为 k - pre - suf,其他未知的a[i]=-inf;suf为最大的后缀,pre为最大的前缀

 代码

const int N = 2e5 + 10;
const LL inf = 1e18;

LL n,m,k;
// vector<LL> a;
LL a[N];
char s[N];

void solve()
{
	cin >> n >> k;
	for (int i = 1;i <= n;i ++) cin >> s[i];	
	for (int i = 1;i <= n;i ++) cin >> a[i];
	
	
	LL sum = 0;
	bool hasK = false;
	LL c1 = 0;
	for (int i = 1;i <= n;i ++)
	{
		if (s[i] == '0')
		{
			sum = 0;
			continue;
		}
		
		c1 ++;
		
		sum = max(sum,0LL) + a[i];//最大字段和
		if (sum > k)
		{
			cout << "No" << endl;
			return;
		}
		else if (sum == k) hasK = true;
	}
	
	if (c1 == n)//全1
	{
		if (!hasK) cout << "No" << endl;
		else 
		{
			cout << "Yes" << endl;
			for (int i = 1;i <= n;i ++)  
				cout << a[i] << " ";
			cout << endl;
		}
		return;
	}
	
	for (int i = 1;i <= n;i ++)
	{
		if (s[i] == '0')
		{
			LL l = i - 1,r = i + 1;
			LL suf = 0,pre = 0,t = 0;
			while(l >= 1 && s[l] == '1')
			{
				t += a[l];
				suf = max(suf,t);
				l --;
			}
			t = 0;
			while(r <= n && s[r] == '1')
			{
				t += a[r];
				pre = max(pre,t);
				r ++;
			}
			
			a[i] = k - suf - pre;
			
			cout << "Yes" << endl;
			
			for (int j = 1;j <= n;j ++)
			{
				if (s[j] == '0')
					cout << (j == i ? a[j] : -inf) << " ";
				else cout << a[j] << " ";
			}
			
			cout << endl;
			
			return;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值