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;
},用双端队列也可以,但是我不太懂。。