Codeforces- Educational Codeforces Round 69

A题 DIY Wooden Ladder

签到题,求n-2和第二大的最小值

#include<bits/stdc++.h>
using namespace std;
int arr[100020];
int main()
{
	int t,n;cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=0;i<n;i++)
			cin>>arr[i];
		sort(arr,arr+n);
		cout<<min(arr[n-2]-1,n-2)<<endl;
	}
	return 0;
}

B题 Pillars

水题,求峰值,两边扫描,若不单调为NO

#include<bits/stdc++.h>
using namespace std;
int arr[200020];
int brr[200020];
int main()
{
	int n;cin>>n;bool flag=false;int cnt=0;int maxa=0;
	for(int i=0;i<n;i++)
	{
		cin>>arr[i];
		if(maxa<arr[i])
		{
			maxa=arr[i];
			cnt=i;
		}
	}
	for(int  i=0;i<cnt-1;i++)
		if(arr[i]>arr[i+1])
		{
			cout<<"NO"<<endl;
			return 0;
		}
	for(int i=cnt+1;i<n-1;i++)
	{
		if(arr[i]<arr[i+1])
		{
			cout<<"NO"<<endl;
			return 0;
		}
	}
	cout<<"YES"<<endl;

	return 0;
}

C题 Array Splitting

差分区间,排序后删去后K-1个区间的差,求前面所有差的和

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0) 
#define ll long long
using namespace std;
int n,k,arr[300030];
vector<int>brr;
int main()
{
	cin>>n>>k;
	if(n==k)
	{
		cout<<0<<endl;
		return 0;
	}
	for(int i=0;i<n;i++)
	{
		cin>>arr[i];
		if(i!=0)brr.push_back(arr[i]-arr[i-1]);
		
	}
	sort(brr.begin(),brr.end());
	ll sum=0;
	for(int i=0;i<brr.size()-k+1;i++)
	{
		sum+=brr[i];
	}
	cout<<sum<<endl;
	
	return 0;
}

D题 Yet Another Subarray Problem

dp题,有原公式 $\sum_{i=l}^r{a_i}-k* [(l-r+1)/m] $ ,得出全部用前缀和转换后的公式 $S_r-S_l-k*[(r-l)/m] $ 。
构造一个\(m\)大小的数组,存放每次循环一个\(m\)大小的段取得的最小值即 \(S_l\),用\(res\)存放i选取的\(r\)的值的最大值,即 \(res=max(res,S_i-min(f)-k*[(i-l)/m)]\)
对于取余\(>=0\)的多减去一个\(k\)即可。

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FOR2(i,a,b) for(int i=a;i<=b;i++)
#define sync ios::sync_with_stdio(false);cin.tie(0) 
#define ll long long
using namespace std;
ll n,m,k,arr[300030],res=0,f[20];
int main()
{
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>arr[i];
	}
	FOR(i,0,20)f[i]=0;
	f[0]=-k;
	for(int i=1;i<=n;i++)
	{
		arr[i]+=arr[i-1];//前缀和
		for(int j=0;j<m;j++)
		{
			if(j>=i%m){//未超过一段 
				res=max(res,arr[i]-f[j]-k*(i/m+1));//前缀和-最小值前缀和 
			}	
			else
			{//超过一段+1 
				res=max(res,arr[i]-f[j]-k*(i/m+2));
			}
		} 
		f[i%m]=min(f[i%m],arr[i]-k*(i/m+1));//所有的m段中现存最小值 
	}
	
	cout<<res<<endl;
	return 0;
}
posted @ 2019-07-23 19:39  一块钱的争论  阅读(298)  评论(0编辑  收藏  举报