正题
纪中题目链接:https://jzoj.net/senior/#main/show/3487
题目大意
有两个东西
一个是表示可以选择这个东西,然后加x的价值。
一个是在这个操作之前不可以超过x个东西。
求最大价值
解题思路
我们考虑每个不能超过的操作,我们留下价值最大的。我们可以用这个思路,先将能装的装了,然后到达第二个操作就留下价值最大的。
我们可以用一个小根堆来计算,然后每个东西最多被丢一次,所以时间复杂度:O(nlog n)O(nlogn)
code
#include<cstdio>
#include<algorithm>
#define N 200010
using namespace std;
int cnt,x,num,a[N],ans;
void up(int x)//维护堆
{while(x>1&&a[x/2]>a[x]){swap(a[x/2],a[x]);x/=2;}
}
void down(int x)//维护堆
{int y;while(x*2<=num&&a[x*2]<a[x]||x*2+1<=num&&a[x*2+1]<a[x]){y=x*2;if(y<num&&a[y]>a[y+1]) y++;swap(a[x],a[y]);x=y;}
}
int main()
{scanf("%d",&cnt);for(int i=1;i<=cnt;i++){char ch=getchar();while (ch!='c'&&ch!='e') ch=getchar();scanf("%d",&x);if(ch=='c'){a[++num]=x;ans+=x;up(num);}//能装就装else if(i!=cnt){while(num>=x){ans-=a[1];swap(a[1],a[num]);num--;down(1);}//丢到允许}}printf("%d",ans);
}