Educational Codeforces Round 154 (Rated for Div. 2) 补题(C,D)

C Queries for the Array

题目链接:https://codeforces.com/contest/1861/problem/C

思路:

我们采用2个变量 c n t 0 , c n t 1 cnt_0,cnt_1 cnt0,cnt1,分别记录当前序列未排序的长度,和排序的长度,依次更新这两变量的值,这里我们认为一个未排序的序列只有最后一个数是混乱的(3 4 5 6 2/4 5 6 8 2)。

代码演示:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 2e5 + 10;
const int P = 131;  //转换成P进制

int n;
string str;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int t;
	cin >> t;
	while (t--) {
		cin>>str;
		int cnt0=0,cnt1=1;  //当前未排序的长度,已排序的长度
		bool flag=false;
		int len=0; //序列长度
		for(int i=0; i<str.size(); i++) {
			if(str[i]=='+') len++;
			if(str[i]=='-') {
				len--;
				if(cnt0>len) cnt0=0;
				//我们认为未排序的情况是最后一个数是乱的即(3 4 5 6 4/5 6 7 2)
				if(cnt1>len) cnt1=max(1,len);
				//更新排序的长度
			}
			if(str[i]=='1') {
				if(cnt0==0) {  //如果存在未排序的序列
					cnt1=max(1,len);
				}
				else {
					flag=true;
					break;
				}
			}
			if(str[i]=='0') {
				if(cnt1>=len) {  //这种情况已经把len<2的情况包括了
					flag=true;
					break;
				}
				else {
					if(cnt0==0) cnt0=len;
				}
			}
		}
		if(flag) cout<<"NO\n";
		else cout<<"YES\n";
	}
	return 0;
}

D:Sorting By Multiplication

题目链接:https://codeforces.com/contest/1861/problem/D

思路:

其实我们可以看出,对于一个序列来说,让其变为严格递增序列的次数就是序列中 a i ≤ a i + 1 a_i \le a_{i+1} aiai+1的对数,同理,变为严格递减序列的次数就是 a i + 1 ≤ a i a_{i+1} \le a_i ai+1ai的对数,由题意可知,我们可以让 [ l , r ] [l,r] [l,r]这个区间乘一个负数,这就意味着我们可以让一个严格递减序列经过一次操作就变为严格递增序列。这样的话,我们可以分为两段,一段严格递减,一段严格递增,枚举递减和递增的分界点,这里我们要注意的是,我们必须选择让前面是递减的,后面的递增的,如果后面选择递减的话,我们将其反转,最后都会变成负数。

代码演示:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 2e5 + 10;
const int P = 131;  //转换成P进制

int t,n;
ll a[N];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin>>t;
	while(t--) {
		cin>>n;
		for(int i=1; i<=n; i++) cin>>a[i];
		ll b[N];
		b[n+1]=b[n]=0;  //初始化
		for(int i=n-1; i>=1; i--) {  //前缀和预处理,要让后面都变成递增的需要多少次
			if(a[i]>=a[i+1]) b[i]=b[i+1]+1;
			else b[i]=b[i+1];
		}
		ll t=0,ans=b[1],pre=INF;
		for(int i=1; i<=n; i++) {  //枚举节点
			if(a[i]>=pre) t++;  //让前i个数变成递减所需要的次数
			pre=a[i];
			ans=min(ans,b[i+1]+1+t);
		}
		cout<<ans<<"\n";
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值