Codeforces Round #687 (Div. 2, based on Technocup 2021 Elimination Round 2) D题 XOR-gun(思维)

题意:
给出一个长度为n的非递减数组,每次可以选择连续的两个数,将这两个数删除,并将他们的异或值加入到删除的位置,问至少要几次操作才可以让数组不再是非递减。
题解:
1.假如数组中存在连续的三个数,它们的最高位的1都在同一个位置,那么直接让后面两个数异或,这样得到的值必小于第一个。

2.若不存在,说明数组中只可能存在两个连续的数的最高位的1在同一个位置,甚至都不相同,因为元素<=1e9,所以它们的位数不会超过30位,也就是说,假如每一位都有两个连续的数的最高位的1在这一位,数组也只有2*30个元素,然后就可以直接暴力找两个连续区间,判断两个区间异或值大小,求出答案。

结论:当n>=100时,直接输出1,否则暴力找答案。

代码:

#include<bits/stdc++.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int MAXN=1e5+5;
const int mod=1e9+7;
int a[MAXN];
int sum[MAXN];
int main()
{
    
    
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
    
    
		cin>>a[i];
		sum[i]=sum[i-1]^a[i];
	}
	int ans=1e9;
	if(n>=100)
	{
    
    
		ans=1;
	}
	else
	{
    
    
		for(int i=1;i<=n;i++)
		{
    
    
			for(int j=i+1;j<=n;j++)
			{
    
    
				for(int k=i;k<j;k++)
				{
    
    
					int k1=sum[k]^sum[i-1];
					int k2=sum[j]^sum[k];
					if(k1>k2) ans=min(ans,j-i-1);
				}
			}
		}
	}
	if(ans==1e9) cout<<-1<<endl;
	else cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/weixin_45755679/article/details/110355940