zoukankan      html  css  js  c++  java
  • CH5501 环路运输(单调栈)

    传送门

    思路:

      遇到一个环,用正常人类的思想就先把环从中间截断然后将其补成2*n长度的链。环上的最小距离换到链上就是i以n/2为半径范围内的点(画图肉眼可见)。由于两个点是等价的,所以我们考虑有序对(i,j){1<=j<i<=2*n&&i-j<=n/2}

      题目要求最大的a[i]+a[j]+dis(i,j)。在上述条件下,dis(i,j)=i-j。那么就是要求a[i]+a[j]+i-j,只要枚举i,得到最大的a[j]-j就好了,考虑j的取值范围[i-n/2,i-1],用单调栈维护a[i]-j

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    int a[2*maxn],q[2*maxn],tail,head,ans;
    int main()
    {
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++)        scanf("%d",&a[i]);
        for(int i=1+n;i<=2*n;i++)    a[i]=a[i-n];
        int c=n/2;
        for(int i=1;i<=c;i++){
            while(tail&&a[q[tail]]-q[tail]<=a[i]-i)
                tail--;
            q[++tail]=i;
        }
        head=1;
        ans=a[c+1]+c+1-q[head]+a[q[head]];
        for(int i=2;i<=n;i++){
            int id=c-1+i;
            while(head<=tail&&q[head]<i)    head++;
            while(tail>=head&&a[q[tail]]-q[tail]<=a[id]-id)    tail--;
            q[++tail]=id;
            ans=max(ans,a[id+1]+id+1-q[head]+a[q[head]]);
        }
        cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    最长有效括号
    C++ 环形缓存区的实现
    vector的原理与底层实现
    聚合分析与分组
    求两个数的最大公约数
    单例模式
    工厂方法模式
    责任链模式
    适配器模式
    策略模式
  • 原文地址:https://www.cnblogs.com/r138155/p/12642143.html
Copyright © 2011-2022 走看看