蛮有意思的的一道题,最后要判断能否成为一种1~n的全排列,我最这样做的:
整个数组先排序一下。假设遍历到了i,那就判断前面b和r的个数,但是有想到了后面可能还会对前面的结果产生影响,所以就抛弃了这个想法。
然后就想:既然是一种排序,那么能不能先把这个排序确定下来呢,事实上是可以的。
做法就成了这样子:整个数组还是先排序,降序排序,然后把r放在b前面。(一会解释)
假如说现在变成了这样:
6 4 4 3 3 1(r r b r b r)
那么6可以变成6,4也可以变成5,4也可以变成4,3也可以变成3,3也可以变成2,1也可以变成1
这样就变成了6 5 4 3 2 1
但是我实际是升序来写的,因为更方便一点,还有一点就是要注意有时候可能光升序并不能判断出所有情况,还要降序再来一次,所以我reverse了一下。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
struct node{int x;char c;
}a[N];
int t,n;
bool cmp(node a,node b){if(a.x!=b.x)return a.x<b.x;else return a.c<b.c;
}
int main(){cin>>t;while(t--){cin>>n;string s;for(int i=1;i<=n;i++)cin>>a[i].x;cin>>s;for(int i=1;i<=n;i++)a[i].c=s[i-1];sort(a+1,a+n+1,cmp);int f1=0;for(int i=1;i<=n;i++){if(a[i].x==i)continue;else if(a[i].x<i&&a[i].c=='R')continue;else if(a[i].x>i&&a[i].c=='B')continue;else {f1=1;break;}}reverse(a+1,a+1+n);int f2=0;for(int i=1;i<=n;i++){if(a[i].x==i)continue;else if(a[i].x<i&&a[i].c=='R')continue;else if(a[i].x>i&&a[i].c=='B')continue;else {f2=1;break;}}if(f1==0||f2==0)cout<<"YES\n";else cout<<"NO\n";}return 0;
}
这个题肯定是要排序的(根据直觉),那么最好是按照人数要求来降序排序,这样的话遍历到当前的人的要求时候,就不需要再考虑前面的那么人了。
所以我们先排序,然后一次遍历每个人,如果当前的人数要求满足就直接放进来,如果不满足就看情况来踢掉当前队伍中战力最低的人。所以我们还需要一个优先级队列优化。
还有一点需要注意:
在队伍放入两个人后:总战力是60,人数是2
再遍历第三个人的时候,发现人数过多,那么就应该踢掉一个人,此人战力20小于120,所以这个人就踢掉,然后还需要踢一个人,比较此人的战力40小于120,所以也踢掉。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
struct node{ll A,B;
// bool operator>(const node &b)const {return A>b.A;}
}a[N];
bool operator>(const node &a,const node &b){return a.A>b.A;
}
ll ans,n,sum;
priority_queue<node,vector<node>,greater<node> >q;
bool cmp(node a,node b){return a.B>b.B;
}
int main(){cin>>n;for(int i=1;i<=n;i++)cin>>a[i].A>>a[i].B;sort(a+1,a+1+n,cmp);for(int i=1;i<=n;i++){q.push(a[i]);sum+=a[i].A;while(q.size()>a[i].B){sum-=q.top().A;q.pop();}ans=max(ans,sum);}cout<<ans;return 0;return 0;
}