總結:
當某一數組需要動態插入單個元素或者多個並排序且要選用最大值時使用優先隊列
教訓:
如果選用sort函數每次都重新排序時間複雜度過高,即使是自己寫一個for循環時間複雜度也是o(n),但是使用優先隊列則可以降低到o(logn)且自動排序。
例題:
超時代碼
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
long long value;
long long count;
};
int l=1,r;
int f=0;
node a[900000],b[900000],m;
int c[1000000],t;
bool cmp(node a,node b){
if(a.value==b.value)return a.count>b.count;
return a.value>b.value;
}
int main(){
//兩個數組一個是耽誤的,另一個是未開始的根據兩個數組比較來確定每分鐘誰應該先飛
long long n,k;
cin>>n>>k;
long long sum=0;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i].value);
a[i].count=i;
if(i<=k)
b[i]=a[i];
}
t=k+1;
for(int i=k+1;i<=n+k;i++){
if(i<=n){
if(l<t&&i==k+1)
sort(b+l,b+t,cmp);
if(l<t&&b[l].value>a[i].value){
c[b[l].count]=i;
sum+=(i-b[l].count)*b[l].value;
l++;
b[t++]=a[i];
for(int i=t-2;i>=l;i--){//時間複雜度爲o(n),仍然超時
if(b[i].value<b[i+1].value){
m=b[i];
b[i]=b[i+1];
b[i+1]=m;
}
else break;
}
}
else {
c[a[i].count]=i;
// sum+=(i-a[i].count)*a[i].value;
}
}
else {
if(f==0)
sort(b+l,b+t,cmp),f=1;
if(l<t){
c[b[l].count]=i;
sum+=(i-b[l].count)*b[l].value;
l++;
}
}
}
cout<<sum<<endl;
for(int i=1;i<=n;i++)
printf("%lld ",c[i]);
return 0;
}
正確代碼
#include<iostream>
#include<queue>
using namespace std;
struct node{
long long value;
long long count;
friend bool operator <(node a,node b){
if(a.value==b.value)//注意要使航班耽誤時間儘量少
return a.count>b.count;
return a.value<b.value;
}
};
node a[900000],m;
int c[1000000],t;
priority_queue<node>q;
int main(){
//兩個數組耽誤的,未開始的根據兩個數組比較來確定每分鐘誰應該先飛
long long n,k;
cin>>n>>k;
long long sum=0;
int i;
for( i=1;i<=n;i++){
scanf("%lld",&a[i].value);
a[i].count=i;
if(i<=k)
q.push(a[i]);
}
for(int i=k+1;i<=n+k;i++){
if(i<=n){
if(!q.empty()&&q.top().value>a[i].value){
c[q.top().count]=i;
sum+=(i-q.top().count)*((q.top()).value);
q.pop();
q.push(a[i]);
}
else {
c[a[i].count]=i;
}
}
else {
if(!q.empty()){
c[q.top().count]=i;
sum+=(i-q.top().count)*(q.top().value);
q.pop();
}
}
}
cout<<sum<<endl;
for(int i=1;i<=n;i++)
printf("%d ",c[i]);
return 0;
}