Codeforces Round #768 (Div. 2)

A. Min Max Swap

题目链接

题意:

有两个数组,我们可以将同一位置上的两个数相互交换,求两个数组各自的最大值的乘积的最小值

思路:


令第一个数组中每一个位置上的数都比第二个大,然后分别求两个数组的最大值再相乘即可得到结果。


代码:

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int a;
    int b;
} c[1005];
bool comp(node x,node y)
{
    return x.a<y.a;
}
int main()
{
    int t;
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--)
    {
        int n,k;
        cin>>n>>k;
        memset(c,0,sizeof(c));
        for(int i=1; i<=n; i++)
        {
            cin>>c[i].a;
        }
        for(int i=1; i<=n; i++)
        {
            cin>>c[i].b;
        }
        int sum=k;
        sort(c+1,c+1+n,comp);
        for(int i=1; i<=n; i++)

B. Fun with Even Subarrays

题目链接

题意:

每次操作可以使得 al+i=al+k+i,问至少要多少次操作可以使得数组内的元素全部相等。

思路

从数组最后开始向前推即可


代码:

#include<bits/stdc++.h>
#include <bits/stdc++.h>
using namespace std;
int a[200005];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while (t--)
    {
        int n,ans=0;
        cin>>n;
        for (int i=1; i<=n; i++)
        {
            cin>>a[i];
        }
        int i=n-1;
        while (i>0)
        {
            if (a[i]!=a[n])
            {
                ans++;
                i=n-(n-i)*2;
            }
            else i--;
        }
        cout<<ans<<endl;
    }
    return 0;
}


C. And Matching

题目链接

题意:

把0~n-1的所有数两两配对得到 n / 2 对数字,令每对数字的与运算的和等于k,求配对方式,如果不能配对,输出-1

思路


想办法让一组的结果为k,其余的所有结果都为0。
通过分析可知,对于任意的 i & ( n − 1 − k ) = 0,一定存在分组方式,让 n − 1和 k 配对,0 和 n − k 配对,其他数字使用上述结论处理。
这时 sum = ( ( n − 1 ) & k ) + ( 0 & ( n − k ) ) + 0 + . . . + 0 = k + 0 + 0 + . . . + 0 = k满足题意。

可以发现,当 k = n-1 时,上述操作不成立,当 k = n-1 时,让 n-1 与 n-2 配对,1 和 3 配对,0 和 n-4 配对,其他数字使用上述结论处理。
这时sum=((n−1)&(n−2))+(1&3)+(0&(n−4))+0+…+0=n−2+1+0+0+…+0=n−1=k,满足题意。

通过分析样例可以得知,当 n = 4 时,不存在这样的操作,所以输出 -1。

代码:

#include<bits/stdc++.h>
using namespace std;
const int mo=998244353;
int n,t,a[200005],b[200005],cnt,to[200005];
vector<int> pos[200005];

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>n;
        cnt=0;
        for(int i=0; i<=n; i++)
        {
            pos[i].clear();
        }
        memset(to,0,sizeof(to));
        for(int i=1; i<=n; i++)
        {
            cin>>a[i];
            pos[a[i]].push_back(i);
        }
        int stp=0,st;

        while(stp<n)
        {
            stp++;
            for(int i=0;; i++)
            {
                while(to[i]<pos[i].size() && pos[i][to[i]]<stp)
                {
                    to[i]++;
                }
                if(to[i]==pos[i].size())
                {
                    b[++cnt]=i;
                    for(int j=0; j<i; j++)
                        stp=max(stp,pos[j][to[j]]);
                    break;
                }
            }
        }
        cout<<cnt<<endl;
        for(int i=1; i<=cnt; i++) 
        {
            cout<<b[i]<<' ';
        }
        cout<<endl;
    }
}



D、Range and Partition

题目链接

题意:

找到一个区间 [x,y],使得数组 a 可以划分为 k 个区间,且每个区间满足“区间内元素在[x,y] 的个数严格大于不在[x,y]的元素个数”,输出任意一组 x,y(要求y-x最小) 以及划分方法。

思路


定义数组a中在区间[x,y]的元素个数为 cnt。
如果满足cnt−(n−cnt)>=k,那么一定存在一种划分方法满足要求。
双指针枚举 1到 n 找到合法的并且 y − x最小的一组(x,y),先划分 k-1 满足的小区间(设区间长度为 len,cnt−(len−cnt)=1),留下的元素构造最后一个区间即可。

代码:

#include<bits/stdc++.h>
using namespace std;
int a[1000005], v[1000005];
int main() {
	
	int t;
	ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
	cin >> t;
	while(t--)
	{
		int n, k;
		cin >> n >> k;
		for(int i = 1; i <= n; i++) 
			v[i] = 0;
		for(int i = 1; i <= n; i++) 
		{
			cin >> a[i],;
			v[a[i]]++;
		}
		int l = 1, r = 0, x = 1, y = n;
		int cnt = 0;
		while(r < n)
		{
			cnt += v[++r];
			while(cnt - (n - cnt) >= k)
			{
				if(r-l < y-x) 
				{
					x = l, y = r;
				}
				if(l+1 <= r) 
				{
					cnt -= v[l++];
				}
				else 
					break;
			}
		}
		cout << x << " " << y << endl;
		int pos = 1; cnt = 0;
		for(int i = 1; i <= n; i++)
		{
			if(cnt+1 == k)
			{
				cout << i << ' ' << n << endl;
				break;
			}
			int cnt1 = 0, cnt2 = 0;
			for(int j = i; j <= n; j++)
			{
				if(a[j] >= x && a[j] <= y) cnt1++;
				else cnt2++;
				if(cnt1 - cnt2 > 0)
				{
					pos = j+1;
					break;
				}
			}
			cout << i << " " << pos-1 << endl;
			i = pos-1;
			cnt++;
		}
	}
	return 0;
}




参考题解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值