Codeforces Round #772 (Div. 2)

大佬饶命,只有A,B,C

A. Min Or Sum

题意:给你一个长度为n的一个序列,然后每次可以选择两个位置,可以用随机数x,y来替换这两个位置,但是他们的或运算结果必须相等,求经过无限次的替换,求数组和最小

思路: 怎么让数组和减小,首先0或运算任何数等于他本身,要让和减小,可以让0和他们或运算的结果替换,那么就变成了不断让两个数或运算变小就可,那么替换后的0就参与求和,每次就换少一个数,直至只有一个,换句话说,就是所有数的或运算值的结果就是答案

AC代码 

#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdio>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
using namespace std;
int t,n;
int a[105];
void solve()
{
	int rs = a[1];
	for(int i = 2 ; i <= n ; i++) rs |= a[i];
	cout << rs << endl;
}
int main(){
	IOS;
	cin >> t;
	while(t--){
		cin >> n;
		for(int i = 1 ; i <= n ; i++) cin >> a[i];
		solve();
	}
    return 0;
}

B. Avoid Local Maximums

题意:又给你一个长度为n的序列,然后消除所有的局部最大值(ai > ai - 1  && ai > ai + 1),题目提供了一种操作,每次可以选择一个位置的数替换成任何数,求最小需要操作的次数,然后输出操作后的数组

思路:表面上只需要替换掉所有的局部最大值就可以了,但是看到最后一个样例就是解决这个题的关键,假如按表面上的替换,结果是4,然而结果是2,问题出现在两个局部最大值中间只差一个元素的话,替换掉中间的值就可,就把表面上的两次变成了一个,如果存在这样的情况就替换两个中间的,其余的表面上的替换就可,替换的值用它相邻的最大值替换,避免后面的值受到前面替换的值的影响产生新的局部最大值

AC代码 

#include<iostream>
#include<algorithm>
#include<cmath>
#include<deque>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<stack>
#include<cstdio>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define PII pair<int,int> 
#define PDI pair<double,int> 
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
int t,n;
const int maxn = 2e5+5;
int a[maxn];
vector <int> b; //所有局部最大值的下标
void solve()
{
	b.clear();
	int ans = 0;
	for(int i = 2 ; i < n ; i++){
		if(a[i] > a[i + 1] && a[i] > a[i - 1]){
			b.push_back(i);
		}
	}
	for(int i = 0 ; i < b.size() ; i++){
		ans++;
        //注意下标,避免越界
		if(i + 1 < b.size() && b[i + 1] == b[i] + 2){ //存在相邻的局部最大值
			int pos = (b[i] + b[i + 1]) / 2; 
			a[pos] = max(a[b[i + 1]],a[b[i]]); //替换成相邻最大值
			i++; //可以跳到下下一个位置了
		}
		else a[b[i]] = max(a[b[i] + 1],a[b[i] - 1]);  表面替换
	}
	cout << ans << endl;
	for(int i = 1 ; i <= n ; i++) cout << a[i] << " ";
	cout << "\n";
}
int main(){
	IOS;
	cin >> t;
	while(t--){
		cin >> n;
		for(int i = 1 ; i <= n ; i++) cin >> a[i];
		solve();
	}
    return 0;
}

C. Differential Sorting

 这个题要是没有那个不超过n次操作,假如问最小的话,难得上升一大截

题意:给你一个长度为n的序列,然后你可以选择三个下标 x,y,z (x < y < z) ,可以用Ay - Az 替换Ax,问不超过n次操作是否可以序列变成一个从小到大的序列

思路:首先考虑不可能的情况(解题关键),假如a[n - 1]大于a[n],由于n后面没有位置可选,所以直接就是不可能 ,假如a[n] < 0 , a[n - 1] < a[n],说明要想变成从小到大的序列,所以数必须都为负数,除原本已经从小到大排序,不管怎样,我们考虑最后一步替换,要把ax 变成 ay - az, ay - az > ay,替换后就不能满足 从小到大的排序,所以也是-1,所以最终可能的情况就都在a[n] >= 0 && a[n - 1] < a[n],由于操作次数又我们定夺,我们可以改变前面1 ~ n - 2之间的所有数,y = a[n - 1],z = a[n],y - z 肯定比最后两个数都小,而前面每个数都相等

AC代码

#include<iostream>
#include<algorithm>
#include<cmath>
#include<deque>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<stack>
#include<cstdio>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define PII pair<int,int> 
#define PDI pair<double,int> 
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
int t,n;
const int maxn = 2e5+5;
int a[maxn];
void solve()
{
	if(a[n - 1] > a[n]) cout << -1 << endl;
	else{
		if(a[n] >= 0){
		cout << n - 2 << endl;
		for(int i = 1 ; i <= n - 2 ; i++)
			cout << i << " " << n - 1 << " " << n << "\n";
		}
		else{
			if(is_sorted(a + 1,a + 1 + n)) cout << 0 << endl;  
            //判断是否已经从小到大排序可以直接调用函数
			else cout << -1 << endl;
		}
	}
	
}
int main(){
	IOS;
	cin >> t;
	while(t--){
		cin >> n;
		for(int i = 1 ; i <= n ; i++) cin >> a[i];
		solve();
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值