Problem:
在一个游戏中,tokitsukaze需要在n个士兵中选出一些士兵组成一个团去打副本。
第i个士兵的战力为v[i],团的战力是团内所有士兵的战力之和。
但是这些士兵有特殊的要求:如果选了第i个士兵,这个士兵希望团的人数不超过s[i]。(如果不选第i个士兵,就没有这个限制。)
tokitsukaze想知道,团的战力最大为多少。
Solution:
由于选择第i个人的话要求人数不超过s[i],所以我们在选取第个人的时候,保证剩下的s[i] - 1个人的人数限制都大于等于s[i]并且是价值最大的s[i] - 1个
对于 人数限制都大于等于s[i] 可以通过排序,将人数限制大的排在前面,这样在计算第i个的时候可以保证前面的s都是大于等于第i个的
对于 价值最大的s[i] - 1个 可以维护一个小根堆,遇到人数超限制的时候就把小的删除,直至符合人数限制(此处用优先队列实现
// https://ac.nowcoder.com/acm/problem/50439 #include<bits/stdc++.h> #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define _for(i,s,t) for(int i=s;i<t;i++) #define _rof(i,s,t) for(int i=s;i>t;i--) #define rep(i,s,t) for(int i=s;i<=t;i++) #define per(i,s,t) for(int i=s;i>=t;i--) #define Ri(x) scanf("%d",&x) #define Rii(x,y) scanf("%d%d",&x,&y) #define INF 0x3f3f3f3f using namespace std; template<class T>inline void read(T &res) { char c;T flag=1; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0'; while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag; } typedef long long ll; const int maxn = 1e5 + 10; bool cmp(int a,int b){ return a > b; } struct soldier{ int v,s; friend bool operator < (soldier s1,soldier s2){ return s1.s > s2.s; } }sd[maxn]; priority_queue<int,vector<int>,greater<int> > Q; int main(){ IOS; int n; cin>>n; rep(i,1,n){ cin>>sd[i].v>>sd[i].s; } sort(sd + 1,sd + 1 + n); ll sum = 0,ans = 0; rep(i,1,n){ sum += sd[i].v; Q.push(sd[i].v); while(Q.size() > sd[i].s){ sum -= Q.top(); Q.pop(); } ans = max(ans,sum); } cout<<ans<<endl; return 0; } /** Problem: 在一个游戏中,tokitsukaze需要在n个士兵中选出一些士兵组成一个团去打副本。 第i个士兵的战力为v[i],团的战力是团内所有士兵的战力之和。 但是这些士兵有特殊的要求:如果选了第i个士兵,这个士兵希望团的人数不超过s[i]。(如果不选第i个士兵,就没有这个限制。) tokitsukaze想知道,团的战力最大为多少。 Solution: 由于选择第i个人的话要求人数不超过s[i],所以我们在选取第个人的时候,保证剩下的s[i] - 1个人的人数限制都大于等于s[i]并且是价值最大的s[i] - 1个 对于 人数限制都大于等于s[i] 可以通过排序,将人数限制大的排在前面,这样在计算第i个的时候可以保证前面的s都是大于等于第i个的 对于 价值最大的s[i] - 1个 可以维护一个小根堆,遇到人数超限制的时候就把小的删除,直至符合人数限制(此处用优先队列实现 */