hdu6047-贪心&思维-2017多校(2)-Maximum Sequence

来源:互联网 发布:静安区人民法院知询 编辑:程序博客网 时间:2024/06/06 20:50

http://acm.hdu.edu.cn/showproblem.php?pid=6047
1 给定你一个n长的数组a,和n长的数组b。
问你构造a数组的 下一个n长,
有一个限制。每一个 a[i]需要由 一个b[i]限制。
在 b[i]- i这个长度下,我们要求 a[i]为这个范围内 a[i]-i的最大值。
问你这个数组 n+1- 2*n 的所有 a[i]的和。
1 贪心啊,每次都把最大值放在前面,才方便让后面用到,然后就把b倒着排了一下(如果两个b达到的目的相同的话,就取大的那一个。因为更小意味着更大的范围qwq)。然后就跑。
t了。
2 后来觉得是 查找b的时候有问题,我是每一个b 都跑一遍,找极值的。后来用倍增st维护了一下,把后i个先默认为最大的a来确定的。还是t。
3 st对每一个b 对应的区间的极值的查询都是O(1)的时间复杂度,坑死了,竟然不对,后来比赛完听大佬们的讲解,最大值最大值维护一下就行了,不用倍增st。还是T。
4 我终于意识到了是我对每个b进行判断本身构成了O(n2),又看见大佬说用单调队列或优先队列什么的,于是就看了博客。。。
用优先队列的思想,每次蹦出最大值。
同时维护新增数组 的 值,如果蹦出来的 没有新增数组的大,
那么结果必然在新增数组里,这个时候我就要把 这个 b留给下一个用而不是白白的用!!!这点很重!,wa了两次。
思维还是 too young

#include <bits/stdc++.h>using namespace std;const int MAXN=250006*2;const int mod=1e9+7;typedef long long ll;int a[MAXN];int b[MAXN];bool vis[MAXN];int n;int m;int main(){  int ans;    int maxx=-1;    int mmax[MAXN];    while(~scanf("%d",&n)){    maxx=-1;    memset(mmax,0,sizeof(mmax));    for(int i=1;i<=n;i++){        scanf("%d",&a[i]);        maxx=max(maxx,a[i]-i);        a[i]-=i;    }    mmax[n+1]=0;    for(int i=n;i>=1;i--)         mmax[i]=max(mmax[i+1],a[i]);    priority_queue<int>q;    for(int i=0;i<n;i++){        scanf("%d",&b[i]);        q.push(mmax[b[i]]);    }    int temp=0;//维护最大值。    ll ans=0;     for(int i=n+1;i<=2*n;i++){          if(q.top()>temp)             {a[i]=q.top();q.pop();}          else            a[i]=temp;            temp=max(a[i]-i,temp);          ans+=1ll*a[i]%mod;          a[i]-=i;          //cout<<a[i]<<endl;     }     printf("%lld\n",ans%mod);    }    return 0;}或者不用优先队列,,直接贪心。优先队列的意思是直接找出 弹出b的最大值。但是我们发现这个规律也是确定的,排序后,b[0]肯定是最大的,因为后面的数不可能比他大。依次#include <bits/stdc++.h>using namespace std;const int MAXN=250006*2;const int mod=1e9+7;typedef long long ll;int a[MAXN];int b[MAXN];bool vis[MAXN];int n;int m;int main(){  int ans;    int maxx=-1;    int mmax[MAXN];    while(~scanf("%d",&n)){    maxx=-1;    memset(mmax,0,sizeof(mmax));    for(int i=1;i<=n;i++){        scanf("%d",&a[i]);        maxx=max(maxx,a[i]);        a[i]-=i;    }    mmax[n+1]=0;    for(int i=n;i>=1;i--)         mmax[i]=max(mmax[i+1],a[i]);    for(int i=0;i<n;i++){        scanf("%d",&b[i]);    }    sort(b,b+n);    int temp=mmax[b[0]]-(n+1);//维护最大值。    ll ans=mmax[b[0]];//cout<<temp<<" "<<mmax[b[0]]<<endl;     for(int i=1;i<n;i++){         int tt=max(mmax[b[i]],temp);         //cout<<mmax[b[i]]<<endl;         //cout<<i<<" "<<mmax[b[i]]<<" "<<temp<<endl;         //temp=         ans+=1ll*tt%mod;     }     printf("%lld\n",ans%mod);    }    return 0;},用双端队列也可以,但是我不太懂。。
阅读全文
0 0
原创粉丝点击