【CF1154】题解

A

直接模拟即可。

B

对数组中的值进行排序去重。发现若去重之后的数组中有大于 3 个数时无解,因为无法找到一个点到数轴上四个点的距离均相等。若去重之后的数组中只有三个值,则判断中间的值是否到两边的值相等,若不相等,同理无解,相等则解为距离。若只有两个不同的值,若中点是整数,则答案为中点到左端点的距离,否则为两点之间的距离。若只有一个不同的值,则答案直接为 0。

C

首先去掉整周的情况,先统计出有多少个完整的周。剩下为出发日所在周和结束日所在周的情况。将这两周拼成一周(十四天),枚举出发的时间,计算通过当前的食物可以到达的最远距离,取最大值后加入答案贡献即可。

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define cls(a,b) memset(a,b,sizeof(a))
#define debug(x) printf("x = %d\n",x)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
//const int maxn=
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll read(){
    ll x=0,f=1;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    return f*x;
}
/*--------------------------------------------------------*/

const int s[]={0,1,2,0,2,1,0};
int a,b,c;
ll ans;

void read_and_parse(){
    a=read(),b=read(),c=read();
    ans=min(a/3,min(b/2,c/2));
    a-=ans*3,b-=ans*2,c-=ans*2;
    ans*=7;
}

void solve(){
    int res=0;
    for(int i=0;i<7;i++){
        int ret=0,aa=a,bb=b,cc=c;
        for(int j=i;j<i+7;j++){
            if(s[j%7]==0){
                if(aa)--aa,++ret;
                else break;
            }else if(s[j%7]==1){
                if(bb)--bb,++ret;
                else break;
            }else{
                if(cc)--cc,++ret;
                else break;
            }
        }
        res=max(res,ret);
    }
    printf("%lld\n",ans+res);
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

D

贪心策略:在阳光下且油箱未满的时候,优先采用电平来供电,其他情况下优先采用太阳能供电。

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define cls(a,b) memset(a,b,sizeof(a))
#define debug(x) printf("x = %d\n",x)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=2e5+10;
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll read(){
    ll x=0,f=1;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    return f*x;
}
/*--------------------------------------------------------*/

int n,b,a,now;
bool s[maxn];

void read_and_parse(){
    n=read(),b=read(),a=read(),now=a;
    for(int i=1;i<=n;i++)s[i]=read();
}

void solve(){
    for(int i=1;i<=n;i++){
        if(s[i]==1){
            if(b&&now<a){
                --b,++now;
            }else{
                if(now)--now;
                else return (void)printf("%d\n",i-1);
            }
        }else{
            if(now)--now;
            else if(b)--b;
            else return (void)printf("%d\n",i-1);
        }
    }
    printf("%d\n",n);
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

E

采用双向链表进行模拟整个过程,因为每个人会且仅会被选择一次,因此时间复杂度为 \(O(n)\)

By wzj_xhjbk, contest: Codeforces Round #552 (Div. 3), problem: (E) Two Teams, Accepted, #
 #include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define cls(a,b) memset(a,b,sizeof(a))
#define debug(x) printf("x = %d\n",x)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=2e5+10;
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll read(){
    ll x=0,f=1;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    return f*x;
}
/*--------------------------------------------------------*/

int n,k,a[maxn],d[maxn],tag[maxn],l[maxn],r[maxn];

bool cmp(int x,int y){return a[x]>a[y];}

void read_and_parse(){
    n=read(),k=read();
    for(int i=1;i<=n;i++)a[i]=read(),d[i]=i,l[i]=i-1,r[i]=i+1;// 0 ~ n+1
    sort(d+1,d+n+1,cmp);
}

void solve(){
    int clk=1;
    for(int i=1;i<=n;i++){
        if(tag[d[i]]!=0)continue;
        tag[d[i]]=clk;
        int pos=d[i],cnt=0,lb=0,rb=n+1;
        while(l[pos]&&cnt<k)pos=l[pos],tag[pos]=clk,++cnt;
        if(l[pos])lb=l[pos];
        pos=d[i],cnt=0;
        while(r[pos]<=n&&cnt<k)pos=r[pos],tag[pos]=clk,++cnt;
        if(r[pos]<=n)rb=r[pos];
        r[lb]=rb,l[rb]=lb;
        clk=clk==1?2:1;
    }
    for(int i=1;i<=n;i++)printf("%d",tag[i]);
    puts("");
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

F

不考虑优惠策略,可以发现买 k 个物品的最小值即为所有物品中的前 k 小值之和,因此按照物品的价格进行排序。现在考虑优惠政策,设 \(dp[i]\) 表示买 i 个物品的最小值,则状态转移方程为 \(dp[i]=min\{dp[i],dp[i-a]+\sum\limits_{i=i-a+b+1}^{n}cost[i] \}\)。其中求和部分可以利用前缀和预处理,时间复杂度为 \(O(k*m)\)

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define cls(a,b) memset(a,b,sizeof(a))
#define debug(x) printf("x = %d\n",x)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=2e5+10;
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll read(){
    ll x=0,f=1;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    return f*x;
}
/*--------------------------------------------------------*/

int n,m,k,a[maxn];
ll dp[2010],sum[2010];
P off[maxn];

void read_and_parse(){
    n=read(),m=read(),k=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=m;i++)off[i].fi=read(),off[i].se=read();
    sort(a+1,a+n+1),sort(off+1,off+m+1);
}

void solve(){
    for(int i=1;i<=k;i++)sum[i]=sum[i-1]+a[i],dp[i]=sum[i];
    for(int i=1;i<=k;i++){
        for(int j=1;j<=m;j++){
            if(off[j].fi>i)break;
            dp[i]=min(dp[i],dp[i-off[j].fi]+sum[i]-sum[i-off[j].fi+off[j].se]);
        }
    }
    printf("%lld\n",dp[k]);
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

G

玄学复杂度。。考虑枚举 \(gcd\),每次找到序列中最小的两个数,计算最小公倍数与最优解进行比较即可。

转载于:https://www.cnblogs.com/wzj-xhjbk/p/10724177.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值