正题
纪中题目链接:https://jzoj.net/senior/#main/show/3487
题目大意
有两个东西
一个是表示可以选择这个东西,然后加x的价值。
一个是在这个操作之前不可以超过x个东西。
求最大价值
解题思路
我们考虑每个不能超过的操作,我们留下价值最大的。我们可以用这个思路,先将能装的装了,然后到达第二个操作就留下价值最大的。
我们可以用一个小根堆来计算,然后每个东西最多被丢一次,所以时间复杂度:
O(nlog n)
O
(
n
l
o
g
n
)
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);
}