Codeforces 614

614 D

题意210 题意115

还要加一句话:输出操作后的序列。

思路:
只有两种操作是合法的:

  1. 将所有水平值最小的技能升高
  2. 将水平值最高的技能升高到 \(A\)

于是可以枚举一维,二分一维

解法:处理一个初始水平值的前缀和,暴力枚举操作2,二分出操作1升高到的值,在这个二分的check函数中再写一个二分算出所需的代价看看是否符合条件。\(O(n\log ^2n)\)亲测可过。
至于怎么输出操作后的序列,看代码。

Code

#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef long long D;
typedef pair<D,D> P;
template<typename tp>
void read(tp& x){
    x=0;
    char c=getchar();
    bool sgn=0;
    while((c<'0'||c>'9')&&c!='-')c=getchar();
    if(c=='-')sgn=1,c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    if(sgn)x=-x;
}
template<typename tp>
void write(tp x){
    if(x<0)putchar('-'),write(-x);
    else{
        if(x>=10)write(x/10);
        putchar(x%10+'0');
    }
}
D n,A,cf,cm,m,sum[maxn],res[maxn];
P a[maxn];
bool check(D x,D rest,D i){
    D l=1,r=i-1,mid,I=i;
    while(l<=r){
        mid=(l+r)>>1;
        if(a[mid].first>=x)I=mid,r=mid-1;
        else l=mid+1;
    }
    D II=min(I,i);
    return x*(II-1)-sum[II-1]<=rest;
}
signed main(){
    D cnt=0,cost=0,ANS=-1,MI=-1,POS=-1;
    read(n);read(A);read(cf);read(cm);read(m);
    for(D i=1;i<=n;i++){
        read(a[i].first);
        a[i].second=i;
        if(a[i].first==A)cnt++;
    }
    sort(a+1,a+n+1);
    n-=cnt;
    for(D i=1;i<=n;i++)sum[i]=sum[i-1]+a[i].first;
    for(D i=0;i<=n;i++){
        if(i){
            cost+=A-a[n-i+1].first;
            if(cost>m)break;
        }
        D l=a[1].first,r=A,mid,ans=l;
        while(l<=r){
            mid=(l+r)>>1;
            if(check(mid,m-cost,n-i+1)){
                ans=mid;
                l=mid+1;
            }
            else{
                r=mid-1;
            }
        }
        if((cnt+i)*cf+ans*cm>ANS){
            ANS=(cnt+i)*cf+ans*cm;
            MI=ans;
            POS=i;
        }
    }
    write(ANS),putchar('\n');
    if(MI!=-1&&POS!=-1){
        for(D i=n-POS+1;i<=n;i++)a[i].first=A;
        for(D i=1;a[i].first<MI&&i<n-POS+1;i++)a[i].first=MI;
    }
    n+=cnt;
    for(D i=1;i<=n;i++)res[a[i].second]=a[i].first;
    for(D i=1;i<=n;i++)write(res[i]),putchar(' ');
    return 0;
}

614 E

题意

给一个环形项链,每个珠子是一个字母,现在给出项链长度 \(n\) 和每种字母出现的次数,在某个位置剪开,展开后的字符串是一个回文串,要求构造一个项链,使这种位置的个数最多。

Examples

Input
3
4 2 1
Output
1
abacaba
Input
1
4
Output
4
aaaa
Input
2
1 1
Output
0
ab

算法: \(\text{gcd}\)

猜你喜欢

转载自www.cnblogs.com/BlogOfchc1234567890/p/10366678.html