Codeforces Round 973 (Div. 2) D题

六年级蒟蒻来题解了

题目传送门

题目大意

有一道题詹和他的朋友都不会做,然后呢就要求你去完成(真够呛的)(前面都是废话)。告诉你有t组样例每组样例中有一个n和n个数。你可以完成一下亿种操作:

选定一个 i ,这个i的范围是1~n-1,你可以把第 i 个位置减 1,但是与此同时第 i+1 个点必须得加 1 。你可以操作无限次,最后得以保证这些数中的最大数减去最小的数的值最小。

解题思路

首先我们可以把它的每一次操作看成把第 i 号位置的 1 放到了 i+1 里面。我们再来想我们想,既然要让它数组的最大一个数减去最低一个数是最小的,那是不是把这些尽可能的平均一点移多补少是不是就行了呢?答案是肯定的。所以我们可以用一个单调栈去模拟这个过程每一次只要栈里面有数并且平均数大于这数就行了。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int t=1;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        vector<ll> v(n+1);
        for(int i=1;i<=n;i++){
            cin>>v[i];
        }
        stack<pair<ll,int>> s;
        for(int i=1;i<=n;i++){
            ll sum=v[i],cot=1;
            while(!s.empty()&&s.top().first>=sum/cot){
                sum+=s.top().first*s.top().second;
                cot+=s.top().second;
                s.pop();
            }
            s.push({sum/cot,cot-sum%cot});
            if(sum%cot!=0){
                s.push({sum/cot+1,sum%cot});
            }
        }
        ll mx=s.top().first;
        while(s.size()>1){
            s.pop();
        }
        cout<<mx-s.top().first<<'\n';
    }
}

小赞赞为什么不见了!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值