2017多校联合二1003(hdu6047)Maximum Sequence

Maximum Sequence

预处理:a_i -= i ,易证明从最小的b开始选每次选最大的一定可以使结果最大。 证明思路:如果条件改为a_i<=max{a_j-j|b_k<=j<=n},那么b的顺序与最后的结果无关。条件改回来后,由于每次要计算一个数的最大值时都有a_(n+1)...a_(i-1)在范围中,所以每次只需让a_i - i尽可能大,那么就把大的数尽早用上,每次一定考虑尽量多的数字,这样取得的数字就尽可能的大。 所以说每次就是求区间最值,加在答案上。由于贪心的思路,每次要求的区间的下界是单调不降的,故可以用单调队列优化到O(n)的复杂度。 由于1 ≤ b_i ≤ n,对b排序可以用哈希排序(桶排序)完成。 进一步观察,可以发现这样贪心时 a_(n+1)...a_i 其实是单调不增的,所以并不需要每次求区间最值了,选第一个数时就选最大的,后面的选择顺序与最终结果无关了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <string.h>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <list>
#include <bitset>
#include <stack>
#include <stdlib.h>
#define lowbit(x) (x&-x)
#define e exp(1.0)
//ios::sync_with_stdio(false);
//    auto start = clock();
//    cout << (clock() - start) / (double)CLOCKS_PER_SEC;
typedef long long ll;
typedef long long LL;
using namespace std;
const int maxn=250005;
const int mod=1e9+7;
int n;
struct node
{
    int id,value;
};
int a[maxn];
vector<int>b;
int num[maxn];
deque<node>que;
ll ans;
int main()
{
    while(cin>>n)
    {
        ans=0;
        memset(num,0,sizeof(num));
        memset(a,0,sizeof(a));
        que.clear();
        b.clear();
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        int x;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            num[x]++;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=num[i];j++)
                b.push_back(i);
        for(int i=1;i<=n;i++)
        {
            while(!que.empty() && que.back().value<=a[i]-i)
                que.pop_back();
            que.push_back({i,a[i]-i});
        }
        for(int i=1;i<=n;i++)
        {
            while(que.front().id<b[i-1])
                que.pop_front();
            int t=que.front().value;
            ans=(ans+t)%mod;
            t=max(t-n-i,0);
            while(que.back().value<=t)
                que.pop_back();
            que.push_back({n+i,t});
        }
        cout<<ans<<endl;
    }
    return 0;
}


#include <iostream>

#include <algorithm>

#include <cstdio>

#include <cmath>

#include <cstring>

#include <string>

#include <string.h>

#include <map>

#include <set>

#include <queue>

#include <deque>

#include <list>

#include <bitset>

#include <stack>

#include <stdlib.h>

#define lowbit(x) (x&-x)

#define e exp(1.0)

//ios::sync_with_stdio(false);

//    auto start = clock();

//    cout << (clock() - start) / (double)CLOCKS_PER_SEC;

typedef long long ll;

typedef long long LL;

using namespace std;

const int maxn=250005;

const int mod=1e9+7;

int n;

struct node

{

    int id,value;

};

int a[maxn];

vector<int>b;

int num[maxn];

deque<node>que;

ll ans;

int main()

{

    while(cin>>n)

    {

        ans=0;

        memset(num,0,sizeof(num));

        memset(a,0,sizeof(a));

        que.clear();

        b.clear();

        for(int i=1;i<=n;i++)

            scanf("%d",&a[i]);

        int x;

        for(int i=1;i<=n;i++)

        {

            scanf("%d",&x);

            num[x]++;

        }

        for(int i=1;i<=n;i++)

            for(int j=1;j<=num[i];j++)

                b.push_back(i);

        for(int i=1;i<=n;i++)

        {

            while(!que.empty() && que.back().value<=a[i]-i)

                que.pop_back();

            que.push_back({i,a[i]-i});

        }

        for(int i=1;i<=n;i++)

        {

            while(que.front().id<b[i-1])

                que.pop_front();

            int t=que.front().value;

            ans=(ans+t)%mod;

            t=max(t-n-i,0);

            while(que.back().value<=t)

                que.pop_back();

            que.push_back({n+i,t});

        }

        cout<<ans<<endl;

    }

    return 0;

}

另解:

//优先队列

[cpp]  view plain  copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<cmath>  
  5. #include<string>  
  6. #include<algorithm>  
  7. #include<queue>  
  8. #include<stack>  
  9. #include<set>  
  10. #include<map>  
  11. #include<vector>  
  12. using namespace std;  
  13. typedef long long ll;  
  14. const int maxn = 250010;  
  15. const int mod = 1e9+7;  
  16. int n;  
  17. int a[maxn];  
  18. int b[maxn];  
  19. struct Node{  
  20.     int val;  
  21.     int id;  
  22.     friend bool operator < ( const Node &a, const Node &b)  
  23.     {  
  24.         if( a.val != b.val)  
  25.             return a.val < b.val;  
  26.         return a.id > b.id;  
  27.     }  
  28. };  
  29. priority_queue<Node> q;  
  30.   
  31. int main()  
  32. {  
  33.     while( ~scanf("%d",&n))  
  34.     {  
  35.         while( !q.empty())  
  36.             q.pop();  
  37.         Node tmp;  
  38.         forint i = 1; i <= n; i++)  
  39.         {  
  40.             scanf("%d",&a[i]);  
  41.             tmp.id = i;  
  42.             tmp.val = a[i]-i;  
  43.             q.push(tmp);  
  44.         }  
  45.         forint i = 1; i <= n; i++)  
  46.             scanf("%d",&b[i]);  
  47.         sort(b+1,b+1+n);  
  48.         ll ans = 0;  
  49.         int p = 1;  
  50.         while( p <= n)  
  51.         {  
  52.             tmp = q.top();  
  53.             while( b[p] > tmp.id)  
  54.             {  
  55.                 q.pop();  
  56.                 tmp = q.top();  
  57.             }  
  58.             ans=(ans+tmp.val)%mod;  
  59.             tmp.val -= (n+p);  
  60.             tmp.id = n+p;  
  61.             q.push(tmp);  
  62.             p++;  
  63.         }  
  64.         printf("%lld\n",ans);  
  65.     }  
  66.     return 0;  
  67. }  

//单调队列

[cpp]  view plain  copy
  1. #include<cstdio>  
  2. #include<cmath>  
  3. #include<cstring>  
  4. #include<algorithm>  
  5. #include<iostream>  
  6.   
  7. using namespace std;  
  8. #define LL long long  
  9. const int mod = 1e9+7;  
  10. const int maxn = 250010;  
  11. int n;  
  12. int a[maxn];  
  13. int b[maxn];  
  14. struct Node{  
  15.     int id;  
  16.     int val;  
  17. };  
  18. Node q[maxn<<1];  
  19.   
  20. int main()  
  21. {  
  22.     while( ~scanf("%d",&n))  
  23.     {  
  24.         int head = 0;  
  25.         int tail = 0;  
  26.         forint i = 1; i <= n; i++)  
  27.         {  
  28.             scanf("%d",&a[i]);  
  29.             if( tail == 0)  
  30.             {  
  31.                 q[tail].id = i;  
  32.                 q[tail++].val = a[i]-i;  
  33.             }  
  34.             else  
  35.             {  
  36.                 while( head < tail && a[i]-i >= q[tail-1].val)  
  37.                     tail--;  
  38.                 q[tail].id = i;  
  39.                 q[tail++].val = a[i]-i;  
  40.             }  
  41.         }  
  42.         forint i = 1; i <= n; i++)  
  43.             scanf("%d",&b[i]);  
  44.         sort(b+1,b+1+n);  
  45.   
  46.         int p = 1;  
  47.         Node tmp;  
  48.         LL ans = 0;  
  49.         while( p <= n)  
  50.         {  
  51.             while( b[p] > q[head].id)  
  52.                 head++;  
  53.             ans = (ans+q[head].val)%mod;  
  54.             tmp.id = p+n;  
  55.             tmp.val = q[head].val-(n+p);  
  56.             while( head < tail && tmp.val >= q[tail-1].val)  
  57.                 tail--;  
  58.             q[tail++] = tmp;  
  59.             p++;  
  60.         }  
  61.         printf("%lld\n",ans);  
  62.   
  63.     }  
  64.   
  65.     return 0;  
  66. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值