zoukankan      html  css  js  c++  java
  • Neko's loop HDU-6444(网络赛1007)

    题意就是给出n个数,在n个数上每次跳k个数,最多可以跳m次,你可以选择跳任意次,也可以都不跳,问你为了达到目标了快乐值至少在开始的需要多少快乐值。

    题目可以转换成找出循环节,然后再循环节上疯狂试探我可以得到的最大快乐值,然后减一下。

    刚开始想着找循环节,只找了一个,用栈存,然后发现可能会有多个循环节,需要考虑多个循环节的最大值,就转成vector存了。

    对于每一个循环节,先找一次长度为m的序列,但是m可能比我的循环节来的大,所以我考虑循环起来。让 y 表示的我循环起来的圈数,y = m / len, x表示剩余的还没走的数,x = m % len,如果一圈可以获得的最大值,我就可以直接加上它,一开始我y圈的快乐值算成了y*sum,然后再去求最后x步的最大快乐值,然后相加,最后错了...炜神给了样例

    1

    5 1000 30 2

    -1 -2 -3 -4 15

    这时候我可以循环六圈,但是答案却不是这么算的,因为题目说我可以在任何时候停止,所以我可以在从15开始,到第五圈的15的时候提前结束,这样最后的负数我可以不取到,

    所以这时候能直接计算出的最大值只有前y-1圈,然后特判能否循环起来,如果至少可以循环一圈的话,把 x = x + len,对于最后一圈进行特判,求出最后一圈加上剩余一点点步数可以得到的最大的快乐值。然后在相加。

    这时候我最后一步的范围就是(0, 2*len),所以能走到的最大范围是(len-1,3*len),所以在求最大连续子串和的时候前缀和的数量应该开三倍空间。然后这题用deque会wa,可能是爆了吧...

    #include<map>
    #include<set>
    #include<ctime>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lowbit(x) (x & (-x))
    #define INOPEM freopen("in.txt", "r", stdin)
    #define OUTOPEN freopen("out.txt", "w", stdout)
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const double pi = 4.0*atan(1.0);
    const int inf = 0x3f3f3f3f;
    const ll INF = 1e18+100;
    const int maxn = 1e5;
    const int maxm = 1e9+10;
    const int mod = 1e9+7;
    using namespace std;
    
    ll n, m;
    int T, tol;
    ll s, k;
    bool vis[maxn];
    ll a[maxn];
    ll b[maxn];
    ll sum[maxn];
    vector<ll> vec[maxn];
    struct Node {
        int first;
        ll second;
    };
    Node q[maxn];
    
    void init() {
        tol = 0;
        memset(q, 0, sizeof q);
        for(int i=0; i<maxn; i++)    vec[i].clear();
        memset(vis, 0, sizeof vis);
    }
    
    ll solve(int op, int n, ll m) {
        ll ans = 0;
        memset(sum, 0, sizeof sum);
        for(int i=0; i<n; i++)            sum[i] = i==0 ? vec[op][i] : sum[i-1] + vec[op][i];
        for(int i=n; i<2*n; i++)        sum[i] = sum[i-1] + vec[op][i-n];
        for(int i=2*n; i<3*n; i++)         sum[i] = sum[i-1] + vec[op][i-2*n];
    //    for(int i=0; i<3*n; i++)        printf("%lld%c", sum[i], i==3*n-1 ? '
    ' : ' ');
        int head = 0;
        int tail = 0;
        for(int i=0; i<3*n; i++) {
            while(head < tail && q[tail-1].second > sum[i-1])    tail--;
            while(head < tail && q[head].first + m < i)          head++;
            q[tail].first = i-1;
            q[tail].second = sum[i-1];
            tail++;
            if(ans < sum[i] - q[head].second) {
                ans = sum[i] - q[head].second;
            }
        }
        return ans;
    }
    
    int main() {
        int cas = 1;
        scanf("%d", &T);
        while(T--) {
            init();
            scanf("%lld%lld%lld%lld", &n, &s, &m, &k);
            for(int i=0; i<n; i++)    scanf("%lld", &a[i]);
            for(int i=0; i<n; i++) {
                if(!vis[i]) {
                    int pos = i;
                    while(!vis[pos]) {
                        vis[pos] = 1;
                        vec[tol].push_back(a[pos]);
                        pos = (pos + k) % n;
                    }
                    tol++;
                }
            }
    //        for(int i=0; i<tol; i++)    for(int j=0; j<vec[i].size(); j++)    printf("%lld%c", vec[i][j], j==vec[i].size()-1 ? '
    ' : ' ');
            ll ans = -inf;
            for(int i=0; i<tol; i++) {
                ll res = -inf;
                int len = vec[i].size();
                ll tmp = 0;
                for(int j=0; j<len; j++)    tmp += vec[i][j];
                res = solve(i, len, m);
                ans = max(ans, res);
                if(tmp < 0)    continue;
                ll x = m % len;
                ll y = m / len;
                tmp = max(y-1, 0ll) * tmp;
                if(y >= 1)    x += len;
                res = max(res, solve(i, len, x) + tmp);
                ans = max(ans, res);
            }
            ans = max(0ll, s-ans);
            printf("Case #%d: %lld
    ", cas++, ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    VC++中用API调用对话框资源
    《游民文化与中国社会》:类似于《潜规则》从书面的文字中发现背后的规律,偏学术
    转贴:正确认识淋巴瘤
    《知乎周刊·乔布斯往事》:作为书来看内容还有点少并且水平一般
    《我读书少,你可别骗我》;四个搞笑短篇,比较好玩
    《终极问题2.0》:客户满意度的一个非常好的判断方法
    《改革的逻辑》:专家点谈产权制度、土地制度和货币制度,有不少深刻的见解
    《新工业革命》:过于纠缠细节,主题不是很清晰
    《总要有人说出真相》:业余研究者,可读性比较差
    《我在华为的日子》:华为程序员的流水账,可读性比较差
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/9543105.html
Copyright © 2011-2022 走看看