• HDU6444(子段和、分情况比较)


    要点

    • 不难想到gcd一下然后枚举每个开头走一圈,并记录一下数值。
    • 最终答案是分情况的:1.能走几圈走几圈然后加上最后剩余的最大子段和;2.也可能是最后一圈后面的拖后腿了,所以最后一圈没走完就停,即长度为一圈长的最大子段和;3.一圈为负数时只考虑一圈内的即可,多走了反而变差。
    • 求环形的、不超过某长度的最大子段和,用双端队列处理一下前缀和。
    const int maxn = 1e4 + 5;
    int T, n, m, k;
    ll s, a[maxn];
    
    ll calc(vector<ll> v, int length) {
        if (!length)    return 0LL;
    
        ll ret = -INF;
        vector<ll> sum;
        deque<int> Q;//单增的
    
        for (int i = 0; i < length; i++)    v.push_back(v[i]);
        sum.push_back(v[0]);
        for (int i = 1; i < v.size(); i++)  sum.push_back(sum.back() + v[i]);
    
        for (int i = 0; i < v.size(); i++) {
            while (Q.size() && Q.front() + length < i)  Q.pop_front();//保证不超过长度
            ll tmp = sum[i] - (Q.size() ? sum[Q.front()] : 0);//sum[I] - min{sum[j]}
            ret = max(ret, tmp);
    
            while (Q.size() && sum[Q.back()] >= sum[i]) Q.pop_back();//又靠前又大,不用活了
            Q.push_back(i);
        }
        return ret;
    }
    
    ll solve() {
        function<int(int, int)> gcd = [&](int a, int b) { return b ? gcd(b, a % b) : a; };
        int t = gcd(k, n), rest = m % (n / t);
        ll res = 0;
    
        rep(d, 0, t - 1) {
            vector<ll> v;
            ll sum = 0LL;
    
            for (int i = d, j = 1; j <= n / t; j++) {//走完一圈
                v.push_back(a[i]);
                sum += a[i];
                i = (i + k) % n;
                if (i == d) break;
            }
    
            ll tmp = calc(v, rest);//最后“半圈”的最大子段和
            if (m / (n / t) > 0) {//有能力走一圈以上时
                if (sum > 0)
                    tmp = max(tmp + (ll)m / (n / t) * sum, (ll)(m / (n / t) - 1) * sum + calc(v, n / t));
                else    tmp = max(tmp, calc(v, n / t));
            }
    
            res = max(res, tmp);
        }
    
        return res;
    }
    
    int main() {
        read(T);
        for (int kase = 1; kase <= T; kase++) {
            read(n), read(s), read(m), read(k);
            rep(i, 0, n - 1)    read(a[i]);
            printf("Case #%d: %lld
    ", kase, max(0LL, s - solve()));
        }
        return 0;
    }
    
  • 相关阅读:
    2013-11-23 sentence patterns
    面试题 盛水 twitter
    Uva 10025 The ? 1 ? 2 ? ... ? n = k problem
    FTP服务(5)客户连接常见故障现象
    FTP服务(4)基于MySQL数据库认证
    FTP服务(3)实现基于文件验证的vsftpd虚拟用户
    FTP服务(2)实现基于SSL的FTPS
    FTP服务(1)
    Apache httpd服务
    Apache httpd服务——常用配置
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10739351.html
Copyright © 2020-2023  润新知