• FZU 1914 单调队列


    题目链接:http://acm.fzu.edu.cn/problem.php?pid=1914

    题意:

    给出一个数列,如果它的前i(1<=i<=n)项和都是正的,那么这个数列是正的,问这个数列的这n种变换里,

    A(0): a1,a2,…,an-1,an

    A(1): a2,a3,…,an,a1

    A(n-2): an-1,an,…,an-3,an-2

    A(n-1): an,a1,…,an-2,an-1

    问有多少个变换里,所以前缀和都是正整数。

    思路:因为变换是a[n]后面接着a[1]所以我们把数组a接到后面(即a[n+1]=a[1]..a[n+n]=a[n])。然后求一个前缀和。然后对于求以a[i]为起点的变换。即a[i],a[i+1],a[i+2]...a[n]...a[i-1]。当该变换满足全部前缀和都为正时,即a[i],a[i]+a[i+1],...,a[i]+...a[i+n]都为正。但是如果对于每个变换都用O(n)时间去计算每一个前缀和会TLE,所以预处理出原始数列的前缀和。那么上面的前缀和就可以转换成sum[i]-sum[i-1], sum[i+1]-sum[i-1],..,sum[i+n]-sum[i-1]。然后对于题目求的所有前缀和都为正,即在所有前缀和的最小值为正即可。那么就可以用滑动窗口维护最小值。用单调队列实现。 注意STL的deque会TLE,所以自己手写了的双端队列。

    #define _CRT_SECURE_NO_DEPRECATE
    #include<stdio.h>  
    #include<string.h>  
    #include<cstring>
    #include<algorithm>  
    #include<queue>  
    #include<math.h>  
    #include<time.h>
    #include<vector>
    #include<iostream>
    #include<string>
    using namespace std;
    typedef long long int LL;
    const int MAXN = 1e6 + 10;
    LL sum[MAXN];
    struct Deque{
        int head, tail;
        int val[MAXN];
        Deque(){ head = 0; tail = -1; }
        void push_back(int x){ val[++tail] = x; }
        void pop_back(){ tail--; }
        void pop_front(){ head++; }
        int front(){ return val[head]; }
        int back(){ return val[tail]; }
        bool empty(){ return tail < head; }
        void clear(){ head = 0; tail = -1; }
    }deq;
    int main(){
    //#ifdef kirito
    //    freopen("in.txt", "r", stdin);
    //    freopen("out.txt", "w", stdout);
    //#endif
    //    int start = clock();
        int t, n, Ca = 1; scanf("%d", &t);
        while (t--){
            scanf("%d", &n);
            for (int i = 1; i <= n; i++){
                scanf("%lld", &sum[i]);
                sum[i + n] = sum[i];
            }
            for (int i = 2; i <= 2 * n; i++){
                sum[i] += sum[i - 1];
            }
            int ans = 0; LL tmpx = 0;  deq.clear();
            for (int i = 1; i < n; i++){
                while (!deq.empty() && sum[deq.back()] > sum[i]){
                    deq.pop_back();
                }
                deq.push_back(i);
            }
            for (int i = n; i < 2 * n; i++){
                while (!deq.empty() && sum[deq.back()] > sum[i]){
                    deq.pop_back();
                }
                deq.push_back(i);
                while (!deq.empty() && deq.front() <= i - n){
                    deq.pop_front();
                }
                if (sum[deq.front()] - sum[i - n] > 0){
                    ans++;
                }
            }
            printf("Case %d: %d
    ", Ca++, ans);
        }
    //#ifdef LOCAL_TIME
    //    cout << "[Finished in " << clock() - start << " ms]" << endl;
    //#endif
        return 0;
    }
  • 相关阅读:
    UIWebView stringByEvaluatingJavaScriptFromString的使用方法
    手动截图
    KVO与KVC的使用(转)
    LKDBHelper Sqlite操作数据库
    GCD多线程的使用
    ios --- 调用系统"设置"里的功能(转)
    ios开发小技巧(转)
    url字符串中含中文的转码方法
    ios 照片编辑的view封装
    字符串去空格
  • 原文地址:https://www.cnblogs.com/kirito520/p/6098644.html
Copyright © 2020-2023  润新知