Codeforces Round #727 (Div. 2)2021.6.20

Codeforces Round #727 (Div. 2)

闲话:打完省赛打cf,很不在状态地硬撑,wa和t了几次挺傻的地方,d题五分钟云出思路脑抽了调不出来。最后c还fst了。可以算的我拿去while累加,真的是傻了。

A. Contest Start

题意

在这里插入图片描述
n个人参加比赛,每个人开始的时间呈首项x公差x的等差数列,每个人持续时间都是t,当一个人结束时他的贡献等于此时正在比赛或者开始比赛的人。要求总的贡献和。

题解

线性的覆盖问题。
首先t是覆盖长度,特判t超过n*x。
然后统计合理覆盖的部分,即1~k,再计算k+1 ~ n部分。
在这里插入图片描述

code

int main()
{
    ll k;cin>>k;
    while(k--){
        ll n,x,t;cin>>n>>x>>t;
        ll ans=0;
        ll maxn=n*x;
        if(t>=maxn){
            cout<<n*(n-1)/2<<'\n';
            //cout<<"debug:*\n";
            continue;
        }
        ll p=0;
        p=(maxn-t)/x;
        while(p<=(n-1)&&p*x+t<=n*x)p++;
        if(p*x+t>n*x)p--;
        ll evr=t/x;
        ans+=p*evr;
        ll res=n-p;
        if(res>1){
            ans+=res*(res-1)/2;
        }
        //cout<<"debug:"<<p<<'\n';
        cout<<ans<<'\n';
    }
    return 0;
}

补充

感谢@yueshehanjiang的补充,思路差不多,代码很简洁优美。

#define ll long long
using namespace std;
const int N =  1e6 + 10 , M = 1010 , inf = 0x3f3f3f3f , mod = 1e9 + 7 ;
int main()
{
    int k ;
    cin >> k ;
    while(k--)
    {
        ll n , x , t ;
        cin >> n >> x >> t ;
        ll m = t / x ;
        // cout << m << "\n" ;
        if(n - m >= 0) cout << (n - m) * m + (m - 1) * m / 2 << "\n" ;
        else cout << n * (n - 1) / 2 << "\n" ;
    }
    return 0;
}

B. Love Song

题意

在这里插入图片描述
给一段只含小写字母的字符串,它会按照这样的方式变化:a->a,b->bb,c->ccc。以此类推。

题解

预处理加前缀和。

code

map<char,int>mp;
ll sum[100005];
int main()
{
    int w=0;
    for(char c='a';c<='z';c++)mp[c]=++w;
    ll n;cin>>n;
    ll k;cin>>k;
    string s;cin>>s;
    for(int i=1;i<=n;i++){
        if(i==1)sum[i]=mp[s[i-1]];
        else sum[i]=sum[i-1]+mp[s[i-1]];
    }
    //ll len=s.length();
    while(k--){
        ll l,r;cin>>l>>r;
        ll ans=0;
        ll cnt=1;
        ans=sum[r]-sum[l-1];
        cout<<ans<<'\n';
    }
    return 0;
}

C. Stable Groups

题意

在这里插入图片描述
数列分组,合理分组要求排序后相邻项差不超过x。现在可以添加最多k个没出现过的数,要求合理分组的最小组数。

题解

排序,存下相邻项超过x的值。
用k个数去消掉这些超过x的间隙,优先消小的。

code

ll a[200005];
int main()
{
    ll n,k,x;cin>>n>>k>>x;
    for(ll i=0;i<n;i++)cin>>a[i];
    sort(a,a+n);
    vector<ll>b;
    for(ll i=1;i<n;i++){
        ll d=a[i]-a[i-1];
        if(d>x)b.push_back(d);
    }
    ll ans=b.size()+1;
    sort(b.begin(),b.end());
    for(ll i=0;i<b.size();i++){
        ll d=b[i];
        if(ans==1)break;
        if(k==0)break;
        ll now=(d-1)/x;
        if(now>k)break;
        else k-=now,ans--;
    }
    cout<<ans<<'\n';
    return 0;
}

D. PriceFixed

题意

在这里插入图片描述
n个商品,每个商品原价两块。第i个商品有两个值a[i],b[i],分别表示需要购买的数量和可以半价购买的已买商品数量。
要求用最少的钱购买所需商品。

题解

贪心一下,原价购买的尽量以b大的购买,打折购买的尽量以b小的购买。
一开始map搞,结果键值冲突了,用双指针容易一点。

code

int main()
{
    ll n;cin>>n;
    pair<ll,ll>a[n];
    for(ll i=0;i<n;++i)cin>>a[i].second>>a[i].first;
    sort(a,a+n);
    ll ans=0,cnt=0;
    ll l=0,r=n-1;
    while(l<=r){
        ll now=min(a[r].second,max(0ll,a[l].first-cnt));
        cnt+=now;ans+=2ll*now;
        a[r].second-=now;
        if(cnt>=a[l].first){
            ans+=a[l].second;cnt+=a[l].second;l++;
        }
        if(a[r].second==0)r--;
    }
    cout<<ans<<'\n';
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值