CF教育场比赛总结二

一:Educational Codeforces Round 63 (Rated for Div. 2)

C:Alarm Clocks Everywhere
题意:给出n个起始时间x和m个可以选择的事件间隔p,确定一个起始时间和时间间隔使n个起始时间都能被包含进去。
解题思路:找出n个起始时间的相邻时间间隔的最小公约数t,看是否存在p满足p=t,或者p是t的因子,输出p的位置和可选择的起始时间即可。
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int ma=3e5+10;
int n,m,k;
ll a[ma],t,c[ma];
struct node{
    ll x,v;
}b[ma];
bool cmp(node e,node f){
    return e.v<f.v;
}
ll gcd(ll x,ll y){
    if(y==0)return x;
    if(x%y==0)return y;
    else return gcd(y,x%y);
}
ll read() {
    ll y=0,flag=1;
    char ch=getchar();
    while( (ch>'9' || ch<'0') && ch!='-' ) ch=getchar();
    if(ch=='-') flag=-1,ch=getchar();
    while(ch>='0' && ch<='9') y=y*10+ch-'0',ch=getchar();
    return y*flag;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n;i++)c[i]=a[i]-a[i-1];
    t=gcd(c[2],c[3]);
    for(int i=4;i<=n;i++){//计算每个时间段的最小公约数
        t=gcd(c[i],t);
    }
    for(int i=0;i<m;i++){//其实不用结构体排序,这是最开始的思路
        b[i].v=read();
        b[i].x=i+1;
    }
    sort(b,b+m,cmp);
    for(int i=0;i<m;i++){
        if(t%b[i].v==0){//找到满足的p
            cout<<"YES"<<endl;
            if(b[i].v!=a[1]&&b[i].v<a[1])cout<<a[1]-b[i].v<<" "<<b[i].x<<endl;//确定起始时间
            else cout<<a[1]<<" "<<b[i].x<<endl;
            return 0;
        }
    }
    cout<<"NO";
    return 0;
}

D: Beautiful Array
题意:给你一个长度为n的序列,找出一个区间使它区间和最大,或者使该区间乘以k之后的和最大,问最大值是多少。
解题思路:可以用动归的思路:dp[0][i]维护到第i个数不乘k所得到的最大字段和,dp[1][i]维护的是到第i个数以开始使用乘上k的最大子段和,dp[2][i]维护的是到第i个数已经结束乘以k的最大字段和。每次取max即可。
代码如下:

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int ma=3e5+10;
ll n,k,ans;
ll dp[3][ma],x;
ll read() {
    ll y=0,flag=1;
    char ch=getchar();
    while( (ch>'9' || ch<'0') && ch!='-' ) ch=getchar();
    if(ch=='-') flag=-1,ch=getchar();
    while(ch>='0' && ch<='9') y=y*10+ch-'0',ch=getchar();
    return y*flag;
}
int main(){
	n=read(),k=read();
	for(int i=1;i<=n;i++){
        x=read();
        dp[0][i]=max(dp[0][i-1]+x,(ll)0);
        dp[1][i]=max(dp[1][i-1]+x*k,dp[0][i]);
        dp[2][i]=max(dp[2][i-1]+x,dp[1][i]);
        ans=max(ans,dp[2][i]);
	}
	/*
	O(1)内存写法;
	int t1=0,t2=0,t3=0;
	for(int i=0;i<n;++i){
		scanf("%lld",&x);
		t1=max(t1+x,(ll)0);
		t2=max(t2+x*k,t1);
		t3=max(t2,t3+x);
		ans=max(ans,t3);
	}
	*/
	cout<<ans;
	return 0;
}

二:Educational Codeforces Round 69 (Rated for Div. 2)

C: Array Splitting
题意:给出一段递增序列,分成k个连续区间使每一个区间最大值减去最小值的和最小,问最小为多少。
思路:计算相邻两个数之间的差值,如果要保证较小的话,那么只需要将最大的k个差值去掉,使其单独成为一个区间,合并时值为0.
代码如下:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=3e5+10;
int n,m,k,a,b,c,ans;
int num[N];
int read() {
    int y=0,flag=1;
    char ch=getchar();
    while( (ch>'9' || ch<'0') && ch!='-' ) ch=getchar();
    if(ch=='-') flag=-1,ch=getchar();
    while(ch>='0' && ch<='9') y=y*10+ch-'0',ch=getchar();
    return y*flag;
}
int main(){
    n=read(),k=read(),b=read();
    for(int i=2;i<=n;i++){
        a=read();
        num[c++]=a-b;
        b=a;
    }
    sort(num,num+c);
    for(int i=0;i<n-k;i++){
        ans+=num[i];
    }
    cout<<ans;
	return 0;
}

D: Yet Another Subarray Problem
题意:给一个大小为n的数组,给定m, k,计算子序列的在这里插入图片描述的最大值。
解题思路:由表达式可知最后权值中每隔m个就会减k,那么我们对原数组进行处理每隔m个减去k,枚举右端点mod m的数即可。

代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=3e5+10;
ll n,m,k,ans;
ll num[N];
ll read() {
    ll y=0,flag=1;
    char ch=getchar();
    while( (ch>'9' || ch<'0') && ch!='-' ) ch=getchar();
    if(ch=='-') flag=-1,ch=getchar();
    while(ch>='0' && ch<='9') y=y*10+ch-'0',ch=getchar();
    return y*flag;
}
int main(){
    n=read(),m=read(),k=read();
    for(ll i=1;i<=n;i++)num[i]=read();
    for(int j=0;j<m;j++){
        ll now=0;
        for(int i=1;i<=n;i++){
            now+=num[i];
            if(i%m==j)ans=max(ans,now-k),now-=k;
            now=max(now,(ll)0);
        }
    }
    cout<<ans;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值