1 条题解

  • 1
    @ 2019-06-01 11:35:47

    这道题目本来挺难的,但是由于周四晚上的讨论会提到了这道题目,所以就把它放到了第一题。在看提交的时候,发现这题貌似不用单调队列,只要维护前缀和的最小值,然后在环上O(1)转移即可。
    贴上我又臭又长的单调队列代码写法。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    typedef long long ll;
    const int maxn=500000+5;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    int n,l;
    int s[maxn],d[maxn],q[maxn*2];
    int sum[maxn*2],que[maxn*2]; //sum单调递减的序列
    bool f[maxn];
    void init() {
        int tail=0,head=1;
        for(int i=1; i<n; i++) {
            while(head<=tail&&sum[que[tail]]>=sum[i]) tail--;
            que[++tail]=i;
        }
    //  for(int i=1;i<=tail;i++){
    //      cout<<que[tail]<<" ";
    //  }
    //  cout<<endl;
        for(int i=n; i<=2*n; i++) {
            while(head<=tail&&i-que[head]>2*n) head++;
            while(head<=tail&&sum[que[tail]]>=sum[i]) tail--;
            que[++tail]=i;
            if(sum[i]-sum[que[head]]==0) {
    //          cout<<i<<endl;
                f[i-n+1]=true;
            }
        }
    }
    int main() {
        ios::sync_with_stdio(false);
        //freopen("环城旅行.in","r",stdin);
        memset(f,0,sizeof(f));
    //  cout<<!0<<endl;
        cin>>n>>l;
        int sum1=0;
        for(int i=1; i<=n; i++) {
            cin>>d[i]>>s[i]; //距离 加油量
            sum1+=d[i];
        }
        d[n+1]=l-sum1;
        int top1=0,top2=1;
        for(int i=1; i<=n; i++) {
            q[i]=s[i]-d[i+1];
        }
    //  cout<<top1<<" "<<top2<<endl;
        for(int i=n+1; i<=2*n; i++) {
            q[i]=q[i-n];
        }
        for(int i=1; i<=2*n; i++) {
            sum[i]=sum[i-1]+q[i];
        }
    //  for(int i=1;i<=4*n;i++){
    //      cout<<sum[i]<<" ";
    //  }
    //  cout<<endl;
        init();
        bool flag=false;
        for(int i=1; i<=n; i++) {
            if(f[i]) {
                cout<<i<<" ";
                flag=true;
            }
        }
        if(!flag) cout<<-1;
        return 0;
    }
    
    

    然后是不用单调队列的写法。(来自nnu19170323的提交)

    #include <iostream>
    using namespace std;
    
    const int MAXN=500005;
    int n,L;
    int d,s;
    int sum[MAXN];
    int Min=0x7fffffff;
    
    int main()
    {
        cin>>n>>L;
        if(n==1)
        {
            cout<<1<<endl;
            return 0;
        }
        cin>>d;
        for(int i=2;i<=n;i++)
        {
            cin>>s>>d;
            sum[i]=sum[i-1]+s-d;
            if(sum[i]<Min)  Min=sum[i];
        }
        cin >> s; 
        for(int i=1;i<=n;i++)
            if(sum[i]==Min)
                cout<<i<<" ";
        return 0;
    }
    
    
  • 1

信息

ID
1073
难度
6
分类
数据结构 | 单调队列 点击显示
标签
(无)
递交数
25
已通过
10
通过率
40%
上传者